この記事は、「AWS Amplify Advent Calendar 2021」の12日目の記事です。
背景
Amplifyは比較的簡単にwebアプリケーションの基盤を構成するインフラの構築や管理であったりCI/CDの導入などを行うことが可能なサービスである一方で、便利であるが故にAmplifyが用意/想定しているユースケースから違う構成を組もうとすると面倒ということがこれまではありました。
この手の課題はAmplifyだからというものではなく抽象化されたサービスあるあるだと思います。
そんな中、今年11月6日にリリースされたAmplifyの新しい機能は、CDKやCloudFormaitonを使用してAmplifyプロジェクトのバックエンドに対してAmplify上で追加のAWSリソースを関連付ける事が出来るようになりました。
Amplifyで最小限の機能を持ったwebアプリケーションを構築した後、サービスの需要が伸びてきて新たにあれやこれやと機能を追加したくなった際にそのままAmplifyでできるよというイメージですね。
サンプルをやってみよう
何事も手を動かすのが一番、先ずは実際にやってみる。
Reactプロジェクト作成
npx create-react-app amplified-shopping
cd amplified-shopping
Reactプロジェクト初期状態
amplified-shopping % ll
-rw-r--r-- 1 xxxx staff 3362 12 11 23:36 README.md
drwxr-xr-x 1052 xxxx staff 33664 12 11 23:36 node_modules
-rw-r--r-- 1 xxxx staff 822 12 11 23:36 package.json
drwxr-xr-x 8 xxxx staff 256 12 11 23:36 public
drwxr-xr-x 10 xxxx staff 320 12 11 23:36 src
-rw-r--r-- 1 xxxx staff 510617 12 11 23:36 yarn.lock
Amplifyプロジェクト初期化
※-y
:デフォルト設定で初期化
amplify init -y
各設定情報
※-y
無しでinitした場合は下記設定項目をそれぞれ対話的に選択して実行することになります。
Project information
| Name: amplifiedshopping
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: react
| Source Directory Path: src
| Distribution Directory Path: build
| Build Command: npm run-script build
| Start Command: npm run-script start
amplisy init
を実行したことでカレントディレクトリにamplify
ディレクトリが作成される
-rw-r--r-- 1 xxxx staff 3362 12 11 23:36 README.md
drwxr-xr-x 9 xxxx staff 288 12 11 23:41 amplify
drwxr-xr-x 1052 xxxx staff 33664 12 11 23:36 node_modules
-rw-r--r-- 1 xxxx staff 822 12 11 23:36 package.json
drwxr-xr-x 8 xxxx staff 256 12 11 23:36 public
drwxr-xr-x 10 xxxx staff 320 12 11 23:36 src
-rw-r--r-- 1 xxxx staff 510617 12 11 23:36 yarn.lock
配下にはinitで生成されたAWSリソースが定義されたCloudFormationがあります。
中身としてはIAMロール2つとS3バケット1つがそれぞれ作成される記述になっています。
※実際はJsonファイルですがyamlの方が読みやすいので置換しています。
【展開】amplify/#current-cloud-backend/awscloudformation/build/root-cloudformation-stack.yaml
Description: Root Stack for AWS Amplify CLI
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
DeploymentBucketName:
Type: String
Default: DeploymentBucket
Description: Name of the common deployment bucket provided by the parent stack
AuthRoleName:
Type: String
Default: AuthRoleName
Description: Name of the common deployment bucket provided by the parent stack
UnauthRoleName:
Type: String
Default: UnAuthRoleName
Description: Name of the common deployment bucket provided by the parent stack
Outputs:
Region:
Description: CloudFormation provider root stack Region
Value:
Ref: AWS::Region
Export:
Name:
Fn::Sub: "${AWS::StackName}-Region"
StackName:
Description: CloudFormation provider root stack ID
Value:
Ref: AWS::StackName
Export:
Name:
Fn::Sub: "${AWS::StackName}-StackName"
StackId:
Description: CloudFormation provider root stack name
Value:
Ref: AWS::StackId
Export:
Name:
Fn::Sub: "${AWS::StackName}-StackId"
AuthRoleArn:
Value:
Fn::GetAtt:
- AuthRole
- Arn
UnauthRoleArn:
Value:
Fn::GetAtt:
- UnauthRole
- Arn
DeploymentBucketName:
Description: CloudFormation provider root stack deployment bucket name
Value:
Ref: DeploymentBucketName
Export:
Name:
Fn::Sub: "${AWS::StackName}-DeploymentBucketName"
AuthRoleName:
Value:
Ref: AuthRole
UnauthRoleName:
Value:
Ref: UnauthRole
Resources:
DeploymentBucket:
Type: AWS::S3::Bucket
Properties:
BucketName:
Ref: DeploymentBucketName
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
AuthRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: ''
Effect: Deny
Principal:
Federated: cognito-identity.amazonaws.com
Action: sts:AssumeRoleWithWebIdentity
RoleName:
Ref: AuthRoleName
UnauthRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: ''
Effect: Deny
Principal:
Federated: cognito-identity.amazonaws.com
Action: sts:AssumeRoleWithWebIdentity
RoleName:
Ref: UnauthRoleName
CloudFormationのコンソール上でも確認出来ますね。
また、Amplifyコンソール上でも対象のアプリケーションが作成されています。
まだこの段階では何もないのでこれからapiなどをそれぞれ作成していきます。
GraphQL API作成
% amplify add api
? Select from one of the below mentioned services: GraphQL
? Here is the GraphQL API that we will create. Select a setting to edit or continue Continue
? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)
⚠️ WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules
GraphQL schema compiled successfully.
Edit your schema at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema.graphql or place .graphql files in a directory at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema
✔ Do you want to edit the schema now? (Y/n) · yes
? Choose your default editor: Visual Studio Code
Couldn’t find selected code editor (vscode) on your machine.
? Try opening with system-default editor instead? Yes
✅ Successfully added resource amplifiedshopping locally
✅ Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud
schema.graphqlを下記に置き換え
type ShoppingItem @model { #Creates a database for ShoppingItem
id: ID!
ingredient: String
quantity: Float
unit: String
}
type Mutation {
sendSummaryEmail: Boolean @function(name: "sendSummary-${env}")
}
デプロイ
amplify push
⠙ Fetching updates to backend environment: dev from the cloud.
⚠️ WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules
GraphQL schema compiled successfully.
Edit your schema at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema.graphql or place .graphql files in a directory at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema
✔ Successfully pulled backend environment dev from the cloud.
⠸ Building resource api/amplifiedshopping
⚠️ WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules
GraphQL schema compiled successfully.
Edit your schema at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema.graphql or place .graphql files in a directory at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema
Current Environment: dev
┌──────────┬───────────────────┬───────────┬───────────────────┐
│ Category │ Resource name │ Operation │ Provider plugin │
├──────────┼───────────────────┼───────────┼───────────────────┤
│ Api │ amplifiedshopping │ Create │ awscloudformation │
└──────────┴───────────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes
⚠️ WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules
GraphQL schema compiled successfully.
Edit your schema at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema.graphql or place .graphql files in a directory at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema
⠸ Building resource api/amplifiedshopping
⚠️ WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules
GraphQL schema compiled successfully.
Edit your schema at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema.graphql or place .graphql files in a directory at /Users/xxxx/amplified-shopping/amplify/backend/api/amplifiedshopping/schema
? Do you want to generate code for your newly created GraphQL API Yes
? Choose the code generation language target javascript
? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2
⠴ Updating resources in the cloud. This may take a few minutes...
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
✔ Generated GraphQL operations successfully and saved at ../../../../src/graphql
✔ All resources are updated in the cloud
GraphQL endpoint: https://xxxxxxxxxxxxxxxxxxxxx.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: xxxxxxxxxxxxxxxxxxxxx
今回もCloudFormationにより各AWSリソースがプロビジョニングされています。
【展開】amplify-amplifiedshopping-dev-234028-apiamplifiedshopping.yaml
Parameters:
env:
Type: String
Default: NONE
DynamoDBModelTableReadIOPS:
Type: Number
Default: 5
Description: The number of read IOPS the table should support.
DynamoDBModelTableWriteIOPS:
Type: Number
Default: 5
Description: The number of write IOPS the table should support.
DynamoDBBillingMode:
Type: String
Default: PAY_PER_REQUEST
AllowedValues:
- PAY_PER_REQUEST
- PROVISIONED
Description: Configure @model types to create DynamoDB tables with PAY_PER_REQUEST
or PROVISIONED billing modes.
DynamoDBEnablePointInTimeRecovery:
Type: String
Default: 'false'
AllowedValues:
- 'true'
- 'false'
Description: Whether to enable Point in Time Recovery on the table.
DynamoDBEnableServerSideEncryption:
Type: String
Default: 'true'
AllowedValues:
- 'true'
- 'false'
Description: Enable server side encryption powered by KMS.
AppSyncApiName:
Type: String
Default: AppSyncSimpleTransform
S3DeploymentBucket:
Type: String
Description: An S3 Bucket name where assets are deployed
S3DeploymentRootKey:
Type: String
Description: An S3 key relative to the S3DeploymentBucket that points to the root
of the deployment directory.
Resources:
GraphQLAPI:
Type: AWS::AppSync::GraphQLApi
Properties:
AuthenticationType: API_KEY
Name:
Fn::Join:
- ''
- - Ref: AppSyncApiName
- "-"
- Ref: env
GraphQLAPITransformerSchema3CB2AE18:
Type: AWS::AppSync::GraphQLSchema
Properties:
ApiId:
Fn::GetAtt:
- GraphQLAPI
- ApiId
DefinitionS3Location:
Fn::Join:
- ''
- - s3://
- Ref: S3DeploymentBucket
- "/"
- Ref: S3DeploymentRootKey
- "/schema.graphql"
GraphQLAPIDefaultApiKey215A6DD7:
Type: AWS::AppSync::ApiKey
Properties:
ApiId:
Fn::GetAtt:
- GraphQLAPI
- ApiId
Expires: 1639840236
GraphQLAPINONEDS95A13CF0:
Type: AWS::AppSync::DataSource
Properties:
ApiId:
Fn::GetAtt:
- GraphQLAPI
- ApiId
Name: NONE_DS
Type: NONE
Description: None Data Source for Pipeline functions
ShoppingItem:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL:
Fn::Join:
- ''
- - https://s3.
- Ref: AWS::Region
- "."
- Ref: AWS::URLSuffix
- "/"
- Ref: S3DeploymentBucket
- "/"
- Ref: S3DeploymentRootKey
- "/stacks/ShoppingItem.json"
Parameters:
DynamoDBModelTableReadIOPS:
Ref: DynamoDBModelTableReadIOPS
DynamoDBModelTableWriteIOPS:
Ref: DynamoDBModelTableWriteIOPS
DynamoDBBillingMode:
Ref: DynamoDBBillingMode
DynamoDBEnablePointInTimeRecovery:
Ref: DynamoDBEnablePointInTimeRecovery
DynamoDBEnableServerSideEncryption:
Ref: DynamoDBEnableServerSideEncryption
referencetotransformerrootstackenv10C5A902Ref:
Ref: env
referencetotransformerrootstackGraphQLAPI20497F53ApiId:
Fn::GetAtt:
- GraphQLAPI
- ApiId
referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name:
Fn::GetAtt:
- GraphQLAPINONEDS95A13CF0
- Name
referencetotransformerrootstackS3DeploymentBucket7592718ARef:
Ref: S3DeploymentBucket
referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref:
Ref: S3DeploymentRootKey
DependsOn:
- GraphQLAPITransformerSchema3CB2AE18
FunctionDirectiveStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL:
Fn::Join:
- ''
- - https://s3.
- Ref: AWS::Region
- "."
- Ref: AWS::URLSuffix
- "/"
- Ref: S3DeploymentBucket
- "/"
- Ref: S3DeploymentRootKey
- "/stacks/FunctionDirectiveStack.json"
Parameters:
referencetotransformerrootstackenv10C5A902Ref:
Ref: env
referencetotransformerrootstackGraphQLAPI20497F53ApiId:
Fn::GetAtt:
- GraphQLAPI
- ApiId
referencetotransformerrootstackS3DeploymentBucket7592718ARef:
Ref: S3DeploymentBucket
referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref:
Ref: S3DeploymentRootKey
DependsOn:
- GraphQLAPITransformerSchema3CB2AE18
CustomResourcesjson:
Type: AWS::CloudFormation::Stack
Properties:
Parameters:
AppSyncApiId:
Fn::GetAtt:
- GraphQLAPI
- ApiId
AppSyncApiName:
Ref: AppSyncApiName
env:
Ref: env
S3DeploymentBucket:
Ref: S3DeploymentBucket
S3DeploymentRootKey:
Ref: S3DeploymentRootKey
TemplateURL:
Fn::Join:
- "/"
- - https://s3.amazonaws.com
- Ref: S3DeploymentBucket
- Ref: S3DeploymentRootKey
- stacks
- CustomResources.json
DependsOn:
- GraphQLAPI
- GraphQLAPITransformerSchema3CB2AE18
- ShoppingItem
- FunctionDirectiveStack
Outputs:
GraphQLAPIKeyOutput:
Description: Your GraphQL API ID.
Value:
Fn::GetAtt:
- GraphQLAPIDefaultApiKey215A6DD7
- ApiKey
Export:
Name:
Fn::Join:
- ":"
- - Ref: AWS::StackName
- GraphQLApiKey
GraphQLAPIIdOutput:
Description: Your GraphQL API ID.
Value:
Fn::GetAtt:
- GraphQLAPI
- ApiId
Export:
Name:
Fn::Join:
- ":"
- - Ref: AWS::StackName
- GraphQLApiId
GraphQLAPIEndpointOutput:
Description: Your GraphQL API endpoint.
Value:
Fn::GetAtt:
- GraphQLAPI
- GraphQLUrl
Export:
Name:
Fn::Join:
- ":"
- - Ref: AWS::StackName
- GraphQLApiEndpoint
Description: '{"createdOn":"Mac","createdBy":"Amplify","createdWith":"7.6.3","stackType":"api-AppSync","metadata":{}}'
【展開】amplify-amplifiedshopping-dev-234028-apiamplifiedshopping-180U9-FunctionDirectiveStack-1HF5ANTFE59F1.yaml
Description: An auto-generated nested stack for the @function directive.
AWSTemplateFormatVersion: '2010-09-09'
Conditions:
HasEnvironmentParameter:
Fn::Not:
- Fn::Equals:
- Ref: referencetotransformerrootstackenv10C5A902Ref
- NONE
Resources:
SendSummaryLambdaDataSourceServiceRole5FDDC207:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: appsync.amazonaws.com
Version: '2012-10-17'
SendSummaryLambdaDataSourceServiceRoleDefaultPolicy89AA0443:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action: lambda:InvokeFunction
Effect: Allow
Resource:
Fn::If:
- HasEnvironmentParameter
- Fn::Sub:
- arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:sendSummary-${env}
- env:
Ref: referencetotransformerrootstackenv10C5A902Ref
- Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:sendSummary
Version: '2012-10-17'
PolicyName: SendSummaryLambdaDataSourceServiceRoleDefaultPolicy89AA0443
Roles:
- Ref: SendSummaryLambdaDataSourceServiceRole5FDDC207
SendSummaryLambdaDataSource:
Type: AWS::AppSync::DataSource
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
Name: SendSummaryLambdaDataSource
Type: AWS_LAMBDA
LambdaConfig:
LambdaFunctionArn:
Fn::If:
- HasEnvironmentParameter
- Fn::Sub:
- arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:sendSummary-${env}
- env:
Ref: referencetotransformerrootstackenv10C5A902Ref
- Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:sendSummary
ServiceRoleArn:
Fn::GetAtt:
- SendSummaryLambdaDataSourceServiceRole5FDDC207
- Arn
InvokeSendSummaryLambdaDataSourceInvokeSendSummaryLambdaDataSourceAppSyncFunction653F6BEF:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Fn::GetAtt:
- SendSummaryLambdaDataSource
- Name
FunctionVersion: '2018-05-29'
Name: InvokeSendSummaryLambdaDataSource
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/InvokeSendSummaryLambdaDataSource.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/InvokeSendSummaryLambdaDataSource.res.vtl"
DependsOn:
- SendSummaryLambdaDataSource
MutationsendSummaryEmailResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: sendSummaryEmail
TypeName: Mutation
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- InvokeSendSummaryLambdaDataSourceInvokeSendSummaryLambdaDataSourceAppSyncFunction653F6BEF
- FunctionId
RequestMappingTemplate: |-
## [Start] Stash resolver specific context.. **
$util.qr($ctx.stash.put("typeName", "Mutation"))
$util.qr($ctx.stash.put("fieldName", "sendSummaryEmail"))
{}
## [End] Stash resolver specific context.. **
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.sendSummaryEmail.res.vtl"
Parameters:
referencetotransformerrootstackenv10C5A902Ref:
Type: String
referencetotransformerrootstackGraphQLAPI20497F53ApiId:
Type: String
referencetotransformerrootstackS3DeploymentBucket7592718ARef:
Type: String
referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref:
Type: String
【展開】amplify-amplifiedshopping-dev-234028-apiamplifiedshopping-180U94VGK18QI-ShoppingItem.yaml
Parameters:
DynamoDBModelTableReadIOPS:
Type: Number
Default: 5
Description: The number of read IOPS the table should support.
DynamoDBModelTableWriteIOPS:
Type: Number
Default: 5
Description: The number of write IOPS the table should support.
DynamoDBBillingMode:
Type: String
Default: PAY_PER_REQUEST
AllowedValues:
- PAY_PER_REQUEST
- PROVISIONED
Description: Configure @model types to create DynamoDB tables with PAY_PER_REQUEST
or PROVISIONED billing modes.
DynamoDBEnablePointInTimeRecovery:
Type: String
Default: 'false'
AllowedValues:
- 'true'
- 'false'
Description: Whether to enable Point in Time Recovery on the table.
DynamoDBEnableServerSideEncryption:
Type: String
Default: 'true'
AllowedValues:
- 'true'
- 'false'
Description: Enable server side encryption powered by KMS.
referencetotransformerrootstackenv10C5A902Ref:
Type: String
referencetotransformerrootstackGraphQLAPI20497F53ApiId:
Type: String
referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name:
Type: String
referencetotransformerrootstackS3DeploymentBucket7592718ARef:
Type: String
referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref:
Type: String
Conditions:
HasEnvironmentParameter:
Fn::Not:
- Fn::Equals:
- Ref: referencetotransformerrootstackenv10C5A902Ref
- NONE
ShouldUseServerSideEncryption:
Fn::Equals:
- Ref: DynamoDBEnableServerSideEncryption
- 'true'
ShouldUsePayPerRequestBilling:
Fn::Equals:
- Ref: DynamoDBBillingMode
- PAY_PER_REQUEST
ShouldUsePointInTimeRecovery:
Fn::Equals:
- Ref: DynamoDBEnablePointInTimeRecovery
- 'true'
Resources:
ShoppingItemTable:
Type: AWS::DynamoDB::Table
Properties:
KeySchema:
- AttributeName: id
KeyType: HASH
AttributeDefinitions:
- AttributeName: id
AttributeType: S
BillingMode:
Fn::If:
- ShouldUsePayPerRequestBilling
- PAY_PER_REQUEST
- Ref: AWS::NoValue
PointInTimeRecoverySpecification:
Fn::If:
- ShouldUsePointInTimeRecovery
- PointInTimeRecoveryEnabled: true
- Ref: AWS::NoValue
ProvisionedThroughput:
Fn::If:
- ShouldUsePayPerRequestBilling
- Ref: AWS::NoValue
- ReadCapacityUnits:
Ref: DynamoDBModelTableReadIOPS
WriteCapacityUnits:
Ref: DynamoDBModelTableWriteIOPS
SSESpecification:
SSEEnabled:
Fn::If:
- ShouldUseServerSideEncryption
- true
- false
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
TableName:
Fn::Join:
- ''
- - ShoppingItem-
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- "-"
- Ref: referencetotransformerrootstackenv10C5A902Ref
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
ShoppingItemIAMRole6DDC2C52:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: appsync.amazonaws.com
Version: '2012-10-17'
RoleName:
Fn::Join:
- ''
- - ShoppingItemIAMRole59c021-
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- "-"
- Ref: referencetotransformerrootstackenv10C5A902Ref
ShoppingItemIAMRoleDefaultPolicyCAD24A0A:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- dynamodb:BatchGetItem
- dynamodb:GetRecords
- dynamodb:GetShardIterator
- dynamodb:Query
- dynamodb:GetItem
- dynamodb:Scan
- dynamodb:ConditionCheckItem
- dynamodb:BatchWriteItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
Effect: Allow
Resource:
- Fn::GetAtt:
- ShoppingItemTable
- Arn
- Ref: AWS::NoValue
Version: '2012-10-17'
PolicyName: ShoppingItemIAMRoleDefaultPolicyCAD24A0A
Roles:
- Ref: ShoppingItemIAMRole6DDC2C52
DynamoDBAccess71ABE5AE:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action:
- dynamodb:BatchGetItem
- dynamodb:BatchWriteItem
- dynamodb:PutItem
- dynamodb:DeleteItem
- dynamodb:GetItem
- dynamodb:Scan
- dynamodb:Query
- dynamodb:UpdateItem
Effect: Allow
Resource:
- Fn::Sub:
- arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}
- tablename:
Fn::Join:
- ''
- - ShoppingItem-
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- "-"
- Ref: referencetotransformerrootstackenv10C5A902Ref
- Fn::Sub:
- arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}/*
- tablename:
Fn::Join:
- ''
- - ShoppingItem-
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- "-"
- Ref: referencetotransformerrootstackenv10C5A902Ref
Version: '2012-10-17'
PolicyName: DynamoDBAccess71ABE5AE
Roles:
- Ref: ShoppingItemIAMRole6DDC2C52
ShoppingItemDataSource:
Type: AWS::AppSync::DataSource
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
Name: ShoppingItemTable
Type: AMAZON_DYNAMODB
DynamoDBConfig:
AwsRegion:
Ref: AWS::Region
TableName:
Ref: ShoppingItemTable
ServiceRoleArn:
Fn::GetAtt:
- ShoppingItemIAMRole6DDC2C52
- Arn
DependsOn:
- ShoppingItemIAMRole6DDC2C52
QuerygetShoppingItempostAuth0FunctionQuerygetShoppingItempostAuth0FunctionAppSyncFunctionD0FB91E4:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: QuerygetShoppingItempostAuth0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Query.getShoppingItem.postAuth.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
QueryGetShoppingItemDataResolverFnQueryGetShoppingItemDataResolverFnAppSyncFunctionEB8045E2:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Fn::GetAtt:
- ShoppingItemDataSource
- Name
FunctionVersion: '2018-05-29'
Name: QueryGetShoppingItemDataResolverFn
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Query.getShoppingItem.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Query.getShoppingItem.res.vtl"
DependsOn:
- ShoppingItemDataSource
GetShoppingItemResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: getShoppingItem
TypeName: Query
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- QuerygetShoppingItempostAuth0FunctionQuerygetShoppingItempostAuth0FunctionAppSyncFunctionD0FB91E4
- FunctionId
- Fn::GetAtt:
- QueryGetShoppingItemDataResolverFnQueryGetShoppingItemDataResolverFnAppSyncFunctionEB8045E2
- FunctionId
RequestMappingTemplate:
Fn::Join:
- ''
- - |-
$util.qr($ctx.stash.put("typeName", "Query"))
$util.qr($ctx.stash.put("fieldName", "getShoppingItem"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "AMAZON_DYNAMODB"))
$util.qr($ctx.stash.metadata.put("apiId", "
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- |-
"))
$util.qr($ctx.stash.put("tableName", "
- Ref: ShoppingItemTable
- |-
"))
$util.toJson({})
ResponseMappingTemplate: "$util.toJson($ctx.prev.result)"
QuerylistShoppingItemspostAuth0FunctionQuerylistShoppingItemspostAuth0FunctionAppSyncFunctionE4B7F5A2:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: QuerylistShoppingItemspostAuth0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Query.listShoppingItems.postAuth.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
QueryListShoppingItemsDataResolverFnQueryListShoppingItemsDataResolverFnAppSyncFunctionCDEBD9F6:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Fn::GetAtt:
- ShoppingItemDataSource
- Name
FunctionVersion: '2018-05-29'
Name: QueryListShoppingItemsDataResolverFn
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Query.listShoppingItems.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Query.listShoppingItems.res.vtl"
DependsOn:
- ShoppingItemDataSource
ListShoppingItemResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: listShoppingItems
TypeName: Query
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- QuerylistShoppingItemspostAuth0FunctionQuerylistShoppingItemspostAuth0FunctionAppSyncFunctionE4B7F5A2
- FunctionId
- Fn::GetAtt:
- QueryListShoppingItemsDataResolverFnQueryListShoppingItemsDataResolverFnAppSyncFunctionCDEBD9F6
- FunctionId
RequestMappingTemplate:
Fn::Join:
- ''
- - |-
$util.qr($ctx.stash.put("typeName", "Query"))
$util.qr($ctx.stash.put("fieldName", "listShoppingItems"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "AMAZON_DYNAMODB"))
$util.qr($ctx.stash.metadata.put("apiId", "
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- |-
"))
$util.qr($ctx.stash.put("tableName", "
- Ref: ShoppingItemTable
- |-
"))
$util.toJson({})
ResponseMappingTemplate: "$util.toJson($ctx.prev.result)"
MutationcreateShoppingIteminit0FunctionMutationcreateShoppingIteminit0FunctionAppSyncFunctionA6C0AC09:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: MutationcreateShoppingIteminit0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.createShoppingItem.init.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
MutationcreateShoppingItempostAuth0FunctionMutationcreateShoppingItempostAuth0FunctionAppSyncFunctionE48AE597:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: MutationcreateShoppingItempostAuth0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.createShoppingItem.postAuth.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
MutationCreateShoppingItemDataResolverFnMutationCreateShoppingItemDataResolverFnAppSyncFunction1FB43923:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Fn::GetAtt:
- ShoppingItemDataSource
- Name
FunctionVersion: '2018-05-29'
Name: MutationCreateShoppingItemDataResolverFn
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.createShoppingItem.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.createShoppingItem.res.vtl"
DependsOn:
- ShoppingItemDataSource
CreateShoppingItemResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: createShoppingItem
TypeName: Mutation
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- MutationcreateShoppingIteminit0FunctionMutationcreateShoppingIteminit0FunctionAppSyncFunctionA6C0AC09
- FunctionId
- Fn::GetAtt:
- MutationcreateShoppingItempostAuth0FunctionMutationcreateShoppingItempostAuth0FunctionAppSyncFunctionE48AE597
- FunctionId
- Fn::GetAtt:
- MutationCreateShoppingItemDataResolverFnMutationCreateShoppingItemDataResolverFnAppSyncFunction1FB43923
- FunctionId
RequestMappingTemplate:
Fn::Join:
- ''
- - |-
$util.qr($ctx.stash.put("typeName", "Mutation"))
$util.qr($ctx.stash.put("fieldName", "createShoppingItem"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "AMAZON_DYNAMODB"))
$util.qr($ctx.stash.metadata.put("apiId", "
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- |-
"))
$util.qr($ctx.stash.put("tableName", "
- Ref: ShoppingItemTable
- |-
"))
$util.toJson({})
ResponseMappingTemplate: "$util.toJson($ctx.prev.result)"
MutationupdateShoppingIteminit0FunctionMutationupdateShoppingIteminit0FunctionAppSyncFunction03DE626C:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: MutationupdateShoppingIteminit0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.updateShoppingItem.init.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
MutationupdateShoppingItempostAuth0FunctionMutationupdateShoppingItempostAuth0FunctionAppSyncFunction740FBEF0:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: MutationupdateShoppingItempostAuth0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.updateShoppingItem.postAuth.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
MutationUpdateShoppingItemDataResolverFnMutationUpdateShoppingItemDataResolverFnAppSyncFunctionBABBDB50:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Fn::GetAtt:
- ShoppingItemDataSource
- Name
FunctionVersion: '2018-05-29'
Name: MutationUpdateShoppingItemDataResolverFn
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.updateShoppingItem.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.updateShoppingItem.res.vtl"
DependsOn:
- ShoppingItemDataSource
UpdateShoppingItemResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: updateShoppingItem
TypeName: Mutation
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- MutationupdateShoppingIteminit0FunctionMutationupdateShoppingIteminit0FunctionAppSyncFunction03DE626C
- FunctionId
- Fn::GetAtt:
- MutationupdateShoppingItempostAuth0FunctionMutationupdateShoppingItempostAuth0FunctionAppSyncFunction740FBEF0
- FunctionId
- Fn::GetAtt:
- MutationUpdateShoppingItemDataResolverFnMutationUpdateShoppingItemDataResolverFnAppSyncFunctionBABBDB50
- FunctionId
RequestMappingTemplate:
Fn::Join:
- ''
- - |-
$util.qr($ctx.stash.put("typeName", "Mutation"))
$util.qr($ctx.stash.put("fieldName", "updateShoppingItem"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "AMAZON_DYNAMODB"))
$util.qr($ctx.stash.metadata.put("apiId", "
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- |-
"))
$util.qr($ctx.stash.put("tableName", "
- Ref: ShoppingItemTable
- |-
"))
$util.toJson({})
ResponseMappingTemplate: "$util.toJson($ctx.prev.result)"
MutationdeleteShoppingItempostAuth0FunctionMutationdeleteShoppingItempostAuth0FunctionAppSyncFunctionD47D4CA7:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: MutationdeleteShoppingItempostAuth0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.deleteShoppingItem.postAuth.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
MutationDeleteShoppingItemDataResolverFnMutationDeleteShoppingItemDataResolverFnAppSyncFunction538640D0:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Fn::GetAtt:
- ShoppingItemDataSource
- Name
FunctionVersion: '2018-05-29'
Name: MutationDeleteShoppingItemDataResolverFn
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.deleteShoppingItem.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Mutation.deleteShoppingItem.res.vtl"
DependsOn:
- ShoppingItemDataSource
DeleteShoppingItemResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: deleteShoppingItem
TypeName: Mutation
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- MutationdeleteShoppingItempostAuth0FunctionMutationdeleteShoppingItempostAuth0FunctionAppSyncFunctionD47D4CA7
- FunctionId
- Fn::GetAtt:
- MutationDeleteShoppingItemDataResolverFnMutationDeleteShoppingItemDataResolverFnAppSyncFunction538640D0
- FunctionId
RequestMappingTemplate:
Fn::Join:
- ''
- - |-
$util.qr($ctx.stash.put("typeName", "Mutation"))
$util.qr($ctx.stash.put("fieldName", "deleteShoppingItem"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "AMAZON_DYNAMODB"))
$util.qr($ctx.stash.metadata.put("apiId", "
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- |-
"))
$util.qr($ctx.stash.put("tableName", "
- Ref: ShoppingItemTable
- |-
"))
$util.toJson({})
ResponseMappingTemplate: "$util.toJson($ctx.prev.result)"
SubscriptiononCreateShoppingItempostAuth0FunctionSubscriptiononCreateShoppingItempostAuth0FunctionAppSyncFunction6A23BE99:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: SubscriptiononCreateShoppingItempostAuth0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onCreateShoppingItem.postAuth.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
SubscriptionOnCreateShoppingItemDataResolverFnSubscriptionOnCreateShoppingItemDataResolverFnAppSyncFunction189F1792:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: SubscriptionOnCreateShoppingItemDataResolverFn
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onCreateShoppingItem.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onCreateShoppingItem.res.vtl"
SubscriptiononCreateShoppingItemResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: onCreateShoppingItem
TypeName: Subscription
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- SubscriptiononCreateShoppingItempostAuth0FunctionSubscriptiononCreateShoppingItempostAuth0FunctionAppSyncFunction6A23BE99
- FunctionId
- Fn::GetAtt:
- SubscriptionOnCreateShoppingItemDataResolverFnSubscriptionOnCreateShoppingItemDataResolverFnAppSyncFunction189F1792
- FunctionId
RequestMappingTemplate:
Fn::Join:
- ''
- - |-
$util.qr($ctx.stash.put("typeName", "Subscription"))
$util.qr($ctx.stash.put("fieldName", "onCreateShoppingItem"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "NONE"))
$util.qr($ctx.stash.metadata.put("apiId", "
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- |-
"))
$util.toJson({})
ResponseMappingTemplate: "$util.toJson($ctx.prev.result)"
SubscriptiononUpdateShoppingItempostAuth0FunctionSubscriptiononUpdateShoppingItempostAuth0FunctionAppSyncFunctionA50D451B:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: SubscriptiononUpdateShoppingItempostAuth0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onUpdateShoppingItem.postAuth.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
SubscriptionOnUpdateShoppingItemDataResolverFnSubscriptionOnUpdateShoppingItemDataResolverFnAppSyncFunctionAE9ECF37:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: SubscriptionOnUpdateShoppingItemDataResolverFn
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onUpdateShoppingItem.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onUpdateShoppingItem.res.vtl"
SubscriptiononUpdateShoppingItemResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: onUpdateShoppingItem
TypeName: Subscription
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- SubscriptiononUpdateShoppingItempostAuth0FunctionSubscriptiononUpdateShoppingItempostAuth0FunctionAppSyncFunctionA50D451B
- FunctionId
- Fn::GetAtt:
- SubscriptionOnUpdateShoppingItemDataResolverFnSubscriptionOnUpdateShoppingItemDataResolverFnAppSyncFunctionAE9ECF37
- FunctionId
RequestMappingTemplate:
Fn::Join:
- ''
- - |-
$util.qr($ctx.stash.put("typeName", "Subscription"))
$util.qr($ctx.stash.put("fieldName", "onUpdateShoppingItem"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "NONE"))
$util.qr($ctx.stash.metadata.put("apiId", "
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- |-
"))
$util.toJson({})
ResponseMappingTemplate: "$util.toJson($ctx.prev.result)"
SubscriptiononDeleteShoppingItempostAuth0FunctionSubscriptiononDeleteShoppingItempostAuth0FunctionAppSyncFunction6E719826:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: SubscriptiononDeleteShoppingItempostAuth0Function
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onDeleteShoppingItem.postAuth.1.req.vtl"
ResponseMappingTemplate: "$util.toJson({})"
SubscriptionOnDeleteShoppingItemDataResolverFnSubscriptionOnDeleteShoppingItemDataResolverFnAppSyncFunctionC61ED2BF:
Type: AWS::AppSync::FunctionConfiguration
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
DataSourceName:
Ref: referencetotransformerrootstackGraphQLAPINONEDS2BA9D1C8Name
FunctionVersion: '2018-05-29'
Name: SubscriptionOnDeleteShoppingItemDataResolverFn
RequestMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onDeleteShoppingItem.req.vtl"
ResponseMappingTemplateS3Location:
Fn::Join:
- ''
- - s3://
- Ref: referencetotransformerrootstackS3DeploymentBucket7592718ARef
- "/"
- Ref: referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref
- "/resolvers/Subscription.onDeleteShoppingItem.res.vtl"
SubscriptiononDeleteShoppingItemResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId:
Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
FieldName: onDeleteShoppingItem
TypeName: Subscription
Kind: PIPELINE
PipelineConfig:
Functions:
- Fn::GetAtt:
- SubscriptiononDeleteShoppingItempostAuth0FunctionSubscriptiononDeleteShoppingItempostAuth0FunctionAppSyncFunction6E719826
- FunctionId
- Fn::GetAtt:
- SubscriptionOnDeleteShoppingItemDataResolverFnSubscriptionOnDeleteShoppingItemDataResolverFnAppSyncFunctionC61ED2BF
- FunctionId
RequestMappingTemplate:
Fn::Join:
- ''
- - |-
$util.qr($ctx.stash.put("typeName", "Subscription"))
$util.qr($ctx.stash.put("fieldName", "onDeleteShoppingItem"))
$util.qr($ctx.stash.put("conditions", []))
$util.qr($ctx.stash.put("metadata", {}))
$util.qr($ctx.stash.metadata.put("dataSourceType", "NONE"))
$util.qr($ctx.stash.metadata.put("apiId", "
- Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- |-
"))
$util.toJson({})
ResponseMappingTemplate: "$util.toJson($ctx.prev.result)"
Outputs:
GetAttShoppingItemTableStreamArn:
Description: Your DynamoDB table StreamArn.
Value:
Fn::GetAtt:
- ShoppingItemTable
- StreamArn
Export:
Name:
Fn::Join:
- ":"
- - Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- GetAtt:ShoppingItemTable:StreamArn
GetAttShoppingItemTableName:
Description: Your DynamoDB table name.
Value:
Ref: ShoppingItemTable
Export:
Name:
Fn::Join:
- ":"
- - Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- GetAtt:ShoppingItemTable:Name
GetAttShoppingItemDataSourceName:
Description: Your model DataSource name.
Value:
Fn::GetAtt:
- ShoppingItemDataSource
- Name
Export:
Name:
Fn::Join:
- ":"
- - Ref: referencetotransformerrootstackGraphQLAPI20497F53ApiId
- GetAtt:ShoppingItemDataSource:Name
【展開】amplify-amplifiedshopping-dev-234028-apiamplifiedshopping-180U94VG-CustomResourcesjson.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: An auto-generated nested stack.
Metadata: {}
Parameters:
AppSyncApiId:
Type: String
Description: The id of the AppSync API associated with this project.
AppSyncApiName:
Type: String
Description: The name of the AppSync API
Default: AppSyncSimpleTransform
env:
Type: String
Description: The environment name. e.g. Dev, Test, or Production
Default: NONE
S3DeploymentBucket:
Type: String
Description: The S3 bucket containing all deployment assets for the project.
S3DeploymentRootKey:
Type: String
Description: |-
An S3 key relative to the S3DeploymentBucket that points to the root
of the deployment directory.
Resources:
EmptyResource:
Type: Custom::EmptyResource
Condition: AlwaysFalse
Conditions:
HasEnvironmentParameter:
Fn::Not:
- Fn::Equals:
- Ref: env
- NONE
AlwaysFalse:
Fn::Equals:
- 'true'
- 'false'
Outputs:
EmptyOutput:
Description: An empty output. You may delete this if you have at least one resource
above.
Value: ''
AmazonSNSトピックをカスタムAWSリソースとしてAmplifyプロジェクトに追加
amplify add custom
sampleではCDKを使用していますが、普段はCloudFormationを使うことが多いので今回はCloudFormationを選択しました。
amplifiedshopping % amplify add custom
? How do you want to define this custom resource? … (Use arrow keys or type to filter)
AWS CDK
❯ AWS CloudFormation
amplified-shopping % amplify add custom ?[main]
✔ How do you want to define this custom resource? · AWS CloudFormation
✔ Provide a name for your custom resource · customResource4da9f265
✔ Do you want to access Amplify generated resources in your custom CloudFormation file? (y/N) · yes
? Select the categories you want this custom resource to have access to. custom
⚠️ No resources found for custom
✅ Created skeleton CloudFormation stack in amplify/backend/custom/customResource4da9f265 directory
✔ Do you want to edit the CloudFormation stack now? (Y/n) · no
snsトピックを作成するCloudFormationを作成
※Endpointには任意のアドレスを入力
{
"Description": "sns-topic",
"Parameters": {
"env": {
"Type": "String",
"Description": "Current Amplify CLI env name"
}
},
"Resources": {
"snstopic": {
"Type": "AWS::SNS::Topic",
"Properties": {
"TopicName": {
"Fn::Join": [
"",
[
"sns-topic-amplifiedshopping-",
{
"Ref": "env"
}
]
]
}
}
},
"snstopicsubscription": {
"Type": "AWS::SNS::Subscription",
"Properties": {
"Protocol": "email",
"TopicArn": {
"Ref": "snstopic"
},
"Endpoint": "任意のアドレス"
}
}
}
}
apiとカスタムリソースをデプロイ
amplify push -y
デプロイが完了するとAWS AppsyncやDynamoDB、SNS関連のリソースがそれぞれ作成される。
また、Amplifyコンソール上ではBackend側のAPIタブからGraphQLAPIが作成されていることが確認出来るかと思います。
加えて、AWSから指定したアドレスに対して以下のお知らせが送信されているのでConfirm subscription
のリンクをクリックしてSNSのsubscribedを完了させます。
届いたメール
You have chosen to subscribe to the topic:
arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:sns-topic-amplifiedshopping-dev
To confirm this subscription, click or visit the link below (If this was in error no action is necessary):
Confirm subscription
Please do not reply directly to this email. If you wish to remove yourself from receiving all future SNS subscription confirmation requests please send an email to sns-opt-out
Lambda関数の追加
※function nameはsendSummary
を入力
amplify add function +[main]
? Select which capability you want to add: Lambda function (serverless function)
? Provide an AWS Lambda function name: sendSummary
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Hello World
Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration
- Environment variables configuration
- Secret values configuration
? Do you want to configure advanced settings? Yes
? Do you want to access other resources in this project from your Lambda function? Yes
? Select the categories you want this function to have access to. api
? Select the operations you want to permit on amplifiedshopping Mutation
You can access the following resource attributes as environment variables from your Lambda function
API_AMPLIFIEDSHOPPING_GRAPHQLAPIENDPOINTOUTPUT
API_AMPLIFIEDSHOPPING_GRAPHQLAPIIDOUTPUT
API_AMPLIFIEDSHOPPING_GRAPHQLAPIKEYOUTPUT
ENV
REGION
? Do you want to invoke this function on a recurring schedule? No
? Do you want to enable Lambda layers for this function? No
? Do you want to configure environment variables for this function? No
? Do you want to configure secret values this function can access? No
? Do you want to edit the local lambda function now? Yes
? Choose your default editor: None
Successfully added resource sendSummary locally.
Next steps:
Check out sample function code generated in <project-dir>/amplify/backend/function/sendSummary/src
"amplify function build" builds all of your functions currently in the project
"amplify mock function <functionName>" runs your function locally
To access AWS resources outside of this Amplify app, edit the /Users/kumada/amplified-shopping/amplify/backend/function/sendSummary/custom-policies.json
"amplify push" builds all of your local backend resources and provisions them in the cloud
"amplify publish" builds all of your local backend and front-end resources (if you added hosting category) and provisions them in the cloud
node-fetchのパッケージ追加
cd amplify/backend/function/sendSummary/src
npm install node-fetch@2
※<YOUR-SNS-TOPIC-ARN-HERE>
にはCloudFormationで作成されたSNSのARNを入力
/* Amplify Params - DO NOT EDIT
API_AMPLIFIEDSHOPPING_GRAPHQLAPIENDPOINTOUTPUT
API_AMPLIFIEDSHOPPING_GRAPHQLAPIIDOUTPUT
API_AMPLIFIEDSHOPPING_GRAPHQLAPIKEYOUTPUT
ENV
REGION
Amplify Params - DO NOT EDIT */
const fetch = require("node-fetch")
const AWS = require('aws-sdk')
const sns = new AWS.SNS()
const graphqlQuery = `query listShoppingItems {
listShoppingItems {
items {
id
ingredient
quantity
unit
}
}
}
`
exports.handler = async (event) => {
const response = await fetch(process.env.API_AMPLIFIEDSHOPPING_GRAPHQLAPIENDPOINTOUTPUT, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.API_AMPLIFIEDSHOPPING_GRAPHQLAPIKEYOUTPUT
},
body: JSON.stringify({
query: graphqlQuery,
operationName: "listShoppingItems",
})
})
const result = await response.json()
const shoppingItems = result.data.listShoppingItems.items
await sns.publish({
// For demo purposes hard-coded, normally recommended to use environment variable
TopicArn: "<YOUR-SNS-TOPIC-ARN-HERE>",
Message: `Here's shopping cart summary - ${new Date().toDateString()}:\n` +
`${shoppingItems.map(item => `${item.quantity} ${item.unit} - ${item.ingredient}`)
.join('\n')}`
}).promise().catch(e => console.log(e))
return true
};
[
{
"Action": ["sns:Publish"],
"Resource": ["arn:aws:sns:*:*:sns-topic-amplifiedshopping-${env}"]
}
]
この時点でのAmplifyで管理しているリソースの確認
amplify status
Current Environment: dev
┌──────────┬────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name │ Operation │ Provider plugin │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Function │ sendSummary │ Update │ awscloudformation │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Api │ amplifiedshopping │ No Change │ awscloudformation │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Custom │ customResource4da9f265 │ No Change │ awscloudformation │
└──────────┴────────────────────────┴───────────┴───────────────────┘
GraphQL endpoint: https://xxxxxxxxxxxx.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: xxxxxxxxxxxx
lambda関数デプロイ
amplify push -y
【展開】amplify-amplifiedshopping-dev-234028-functionsendSummary-1UAI16JAJGVBK.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: '{"createdOn":"Mac","createdBy":"Amplify","createdWith":"7.6.3","stackType":"function-Lambda","metadata":{}}'
Parameters:
CloudWatchRule:
Type: String
Default: NONE
Description: " Schedule Expression"
deploymentBucketName:
Type: String
env:
Type: String
s3Key:
Type: String
Conditions:
ShouldNotCreateEnvResources:
Fn::Equals:
- Ref: env
- NONE
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Metadata:
aws:asset:path: "./src"
aws:asset:property: Code
Properties:
Code:
S3Bucket:
Ref: deploymentBucketName
S3Key:
Ref: s3Key
Handler: index.handler
FunctionName:
Fn::If:
- ShouldNotCreateEnvResources
- sendSummary
- Fn::Join:
- ''
- - sendSummary
- "-"
- Ref: env
Environment:
Variables:
ENV:
Ref: env
REGION:
Ref: AWS::Region
Role:
Fn::GetAtt:
- LambdaExecutionRole
- Arn
Runtime: nodejs14.x
Layers: []
Timeout: 25
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName:
Fn::If:
- ShouldNotCreateEnvResources
- amplifiedshoppingLambdaRole84cee484
- Fn::Join:
- ''
- - amplifiedshoppingLambdaRole84cee484
- "-"
- Ref: env
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
lambdaexecutionpolicy:
DependsOn:
- LambdaExecutionRole
Type: AWS::IAM::Policy
Properties:
PolicyName: lambda-execution-policy
Roles:
- Ref: LambdaExecutionRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
Fn::Sub:
- arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*
- region:
Ref: AWS::Region
account:
Ref: AWS::AccountId
lambda:
Ref: LambdaFunction
CustomLambdaExecutionPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: custom-lambda-execution-policy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- sns:Publish
Resource:
- Fn::Sub:
- arn:aws:sns:*:*:sns-topic-amplifiedshopping-${env}
- env:
Ref: env
Effect: Allow
Roles:
- Ref: LambdaExecutionRole
DependsOn: LambdaExecutionRole
Outputs:
Name:
Value:
Ref: LambdaFunction
Arn:
Value:
Fn::GetAtt:
- LambdaFunction
- Arn
Region:
Value:
Ref: AWS::Region
LambdaExecutionRole:
Value:
Ref: LambdaExecutionRole
【展開】amplify-amplifiedshopping-dev-234028-customcustomResource4da9f265-124STK37CCF2A.yaml
Description: '{"createdOn":"Mac","createdBy":"Amplify","createdWith":"7.6.3","stackType":"custom-customCloudformation","metadata":{}}'
Parameters:
env:
Type: String
Description: Current Amplify CLI env name
Resources:
snstopic:
Type: AWS::SNS::Topic
Properties:
TopicName:
Fn::Join:
- ''
- - sns-topic-amplifiedshopping-
- Ref: env
snstopicsubscription:
Type: AWS::SNS::Subscription
Properties:
Protocol: email
TopicArn:
Ref: snstopic
Endpoint: xxxx@xxxx.co.jp
フロントエンド構築
Reactプロジェクトルートディレクトリに移動してライブラリをインストール
npm install aws-amplify recipe-ingredient-parser-v3
index.jsファイルに追記
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Amplify from 'aws-amplify' #追記
import awsconfig from './aws-exports' #追記
Amplify.configure(awsconfig) #追記
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
App.jsを置き換え
import { useEffect, useState } from 'react';
import { API } from 'aws-amplify';
import * as queries from './graphql/queries';
import * as mutations from './graphql/mutations';
import { parse } from 'recipe-ingredient-parser-v3';
function App() {
const [ingredient, setIngredient] = useState()
const [shoppingItems, setShoppingItems] = useState([])
const fetchShoppingList = async () => {
const response = await API.graphql({ query: queries.listShoppingItems })
setShoppingItems(response.data.listShoppingItems.items)
}
useEffect(() => {
fetchShoppingList()
}, [])
return (
<div className="App">
<input value={ingredient} onChange={e => setIngredient(e.target.value)}/>
<button onClick={async () => {
const parsed = parse(ingredient, 'eng')
console.log(parsed)
if (parsed.unit && parsed.ingredient && parsed.quantity) {
setIngredient("")
await API.graphql({
query: mutations.createShoppingItem,
variables: {
input: {
ingredient: parsed.ingredient,
quantity: parsed.quantity,
unit: parsed.unit
}
}
})
fetchShoppingList()
}
}}>Add ingredient</button>
<h1>Ingredients</h1>
<button onClick={fetchShoppingList}>Refresh</button>
<button onClick={async () => {
await API.graphql({
query: mutations.sendSummaryEmail
})
}}>Send summary email</button>
<ul>
{shoppingItems.map(({ ingredient, quantity, unit }) => <li>
<div>{quantity} {unit} - {ingredient}</div>
</li>)}
</ul>
</div>
);
}
export default App;
これでFrontとBackendは完成。
ソースコードを任意のGithubリポジトリにpushしてAmplifyと連携させます。
Amplifyホスティング
amplify add hosting
? Select the plugin module to execute Hosting with Amplify Console (Managed hosting with custom domains, Continuous
deployment)
? Choose a type Continuous deployment (Git-based deployments)
AmplifyコンソールのHosting environments
タブよりGithubを選択してブランチを接続
を押下
リモートブランチの追加画面でリポジトリとブランチをそれぞれ選択
構築設定の構成画面で作成したバックエンド環境を選択、他は項目はデフォルトを指定
プロビジョニング→ビルド→デプロイ→検証の各ステップが自動的に進み、全てが正常に完了したらURLをクリック
アプリケーショの画面が表示されたら成功
数字 単位 品物
の順に入力してAdd ingredient
を押下
6 cup of milk
Send summary email
を押下してSNS経由で指定したアドレスにメールを送信
メールが届いていれば成功。
lambdaの画面で関数が実行された事を確認
見辛いですが、Invocations
MetricsにCountが計上されているのが分かります。
DynamoDBのテーブルにも反映されている事を確認
Appsyncでクエリを実行して値を取得できるか確認
query MyQuery {
listShoppingItems {
items {
quantity
ingredient
unit
}
}
}
まとめ
今回Amplifyでサーバレスアプリケーションを作成して、その後Amplifyの組み込みでは対応していないカスタムリソースの追加を実施しました。その裏側ではCloudFormationによってDynamoDBやAppsync、lambda、IAM、S3などのリソースが作成されており、それぞれが実際に連携しているところまで確認出来ました。裏側の動きを並行して見ていくことでサービスへの理解が深めることができたので、これでまた一歩Amplifyと仲良くなれたと気がします。また、裏側を知ることでAmplifyの強力さも身に沁みました。Amplifyの学習にある程度の慣れが必要ですがそれは他でも同じで、それぞれを個別で環境を用意するとなるとそれもまた大変なので使い所見極めて上手く使っていきたいですね。
掃除
amplify remove custom
amplify remove api
amplify remove function
amplify push -y
amplify delete