$30 off During Our Annual Pro Sale. View Details »

AWS Amplify - Auth/API Category & Vue 構築ハンズオン

AWS Amplify - Auth/API Category & Vue 構築ハンズオン

AWS Amplifyを初めて使う方向けの構築ハンズオン資料です。

Eiji KOMINAMI / 小南英司

January 06, 2020
Tweet

More Decks by Eiji KOMINAMI / 小南英司

Other Decks in Technology

Transcript

  1. 2 Agenda   Amplifyとは   サービスの概要とディレクトリ構造   Amplify CLI  

    Amplify カテゴリ   Amplify構築ハンズオン「チャットサービスを作ろう」   プロジェクトをビルドしてみる   プロジェクトに機能を追加する
  2. 3 始める前に...   事前準備   Amplify CLI のインストール   必要なもの

      AWSアカウント GitHubアカウント $ npm install -g @aws-amplify/cli $ amplify configure
  3. 4 AWS Amplifyとは   モバイル/Webアプリを簡単に実装できるフレームワーク   バックエンド •  対話式のウィザードだけでバックエンドを簡単セットアップ(Amplify CLI)

      フロントエンド •  Vue, React, iOS, Android と簡単に結合可能なライブラリ •  UIコンポーネント   Amplify Console •  フロントエンドのホスティング •  簡単なデプロイ
  4. 5 Amplifyプロジェクトのディレクトリ構造   フロントエンド/バックエンドを単⼀プロジェクトで⼀括管理 PROJECT_ROOT ᵓᴷᴷ amplify/ ᴹ ᵓᴷᴷ .config/

    ᴹ ᴹ ᵓᴷᴷ local-aws-info.json ᴹ ᴹ ᵓᴷᴷ local-env-info.json ᴹ ᴹ ᵋᴷᴷ project-config.json ᴹ ᵓᴷᴷ backend/ ᴹ ᴹ ᵓᴷᴷᴷ api ᴹ ᴹ ᴹ ᵋᴷᴷ threetierappsample ᴹ ᴹ ᴹ ᵋᴷᴷ schema.graphql ᴹ ᴹ ᵓᴷᴷᴷ auth ᴹ ᴹ ᴹ ᵋᴷᴷ threetierappsample ᴹ ᴹ ᴹ ᵋᴷᴷ parameters.json ᴹ ᴹ ᵓᴷᴷ amplify-meta.json ᴹ ᴹ ᵋᴷᴷ awscloudformation ᴹ ᵓᴷᴷ #current-cloud-backend/ ᴹ ᵋᴷᴷ team-provider-info.json ᵋᴷᴷ src/ ᵓᴷᴷ App.vue ᵓᴷᴷ aws-exports.js ᵓᴷᴷ components/ ᵓᴷᴷ graph/ ᴹ ᵓᴷᴷ mutation.js ᴹ ᵓᴷᴷ queries.js ᴹ ᵓᴷᴷ schema.json ᴹ ᵋᴷᴷ subcriptions.js ᵓᴷᴷ main.js ᵓᴷᴷ package.json ᵋᴷᴷ router/ ᵋᴷᴷ index.js amplify/ ディレクトリ → バックエンドの設定を管理    (データベース, 関数, 認証...) src/ ディレクトリ → フロントエンドのコンテンツ    (HTML, Javascript, CSS...)
  5. 6 Amplifyプロジェクトのデプロイ バックエンド Amplify Framework バックエンドを⾃動デプロイ Amplify Console AppSync Cognito

    DynamoDB GraphQL コードの取得 Login ユーザ Webコンテンツ (フロントエンド) 静的コンテンツ PROJECT_ROOT ᵓᴷᴷ amplify/ ᴹ ᵓᴷᴷ .config/ ᴹ ᴹ ᵓᴷᴷ local-aws-info.json ᴹ ᴹ ᵓᴷᴷ local-env-info.json ᴹ ᴹ ᵋᴷᴷ project-config.json ᴹ ᵓᴷᴷ backend/ ᴹ ᴹ ᵓᴷᴷᴷ api ᴹ ᴹ ᴹ ᵋᴷᴷ threetierappsample ᴹ ᴹ ᴹ ᵋᴷᴷ schema.graphql ᴹ ᴹ ᵓᴷᴷᴷ auth ᴹ ᴹ ᴹ ᵋᴷᴷ threetierappsample ᴹ ᴹ ᴹ ᵋᴷᴷ parameters.json ᴹ ᴹ ᵓᴷᴷ amplify-meta.json ᴹ ᴹ ᵋᴷᴷ awscloudformation ᴹ ᵓᴷᴷ #current-cloud-backend/ ᴹ ᵋᴷᴷ team-provider-info.json ᵋᴷᴷ src/ ᵓᴷᴷ App.vue ᵓᴷᴷ aws-exports.js ᵓᴷᴷ components/ ᵓᴷᴷ graph/ ᴹ ᵓᴷᴷ mutation.js ᴹ ᵓᴷᴷ queries.js ᴹ ᵓᴷᴷ schema.json ᴹ ᵋᴷᴷ subcriptions.js ᵓᴷᴷ main.js ᵓᴷᴷ package.json ᵋᴷᴷ router/ ᵋᴷᴷ index.js コードの保存 Amplify プロジェクト
  6. 7 Amplify CLI   対話式ウィザードでバックエンドを簡単に作成できる   Amplify プロジェクトの作成 $ amplify

    init Scanning for plugins... Plugin scan successful Note: It is recommended to run this command from the root of your app directory ? Enter a name for the project test (プロジェクトの名前は?) test ? Enter a name for the environment prod (バックエンドの名前は?) prod ? Choose your default editor: Visual Studio Code (開発環境は?) Visual Studio Code ? Choose the type of app that you‘re building javascript (フロントエンドは?) javascript Please tell us about your project ? What javascript framework are you using vue (javascriptフレームワークは?) vue ? Source Directory Path: src ? Distribution Directory Path: dist ? Build Command: npm run-script build ? Start Command: npm run-script serve Using default provider awscloudformation ? Do you want to use an AWS profile? Yes ? Please choose the profile you want to use Adding backend environment prod to AWS Amplify Console app: XXXXXXXXXX ⠙ Initializing project in the cloud... AWS上でバックエンドの初期化を開始....
  7. 8 Amplify CLI   対話式ウィザードでバックエンドを簡単に作成できる   バックエンドに認証機能を追加 $ amplify add

    auth Using service: Cognito, provided by: awscloudformation Please provide a friendly name for your resource that will be used to label this category in the project: test (この認証機能の名前は?) test Please enter a name for your identity pool. test (Identity Poolの名前は?) test Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) No (未認証ユーザのログインは許可する?) No Do you want to enable 3rd party authentication providers in your identity pool? No (サードパーティの認証プロバイダーは使用する?) No Please provide a name for your user pool: test (User Poolの名前は?) test Warning: you will not be able to edit these selections. How do you want users to be able to sign in? Email (ユーザはどの情報でログインする?) Email Do you want to add User Pool Groups? No (User Poolグループを追加する?) No Do you want to add an admin queries API? No (管理用のAPIは作成する?) No Multifactor authentication (MFA) user login options: OFF (多要素認証は利用する?) OFF Email based user registration/forgot password: Enabled (Requires per-user email entry at registration) (Emailを使ったユーザ登録やパスワード再登録機能を有効化する?) Enabled
  8. 9 Amplify CLI   対話式ウィザードでバックエンドを簡単に作成できる   バックエンドに認証機能を追加(続き) $ amplify add

    auth Using service: Cognito, provided by: awscloudformation Please specify an email verification subject: 認証コード をお送りします (メールアドレス認証を行う際のメールのタイトルは?) 認証コード をお送りします Please specify an email verification message: あなたの認証コードは {####} です。 (メールアドレス認証を行う際のメールの内容は?) あなたの認証コードは {####} です。 Do you want to override the default password policy for this User Pool? No (デフォルトのパスワードポリシーを上書きする?) No Warning: you will not be able to edit these selections. What attributes are required for signing up? Email, Name (ユーザ登録時に何の情報を登録させる?) Email, Name Specify the app‘s refresh token expiration period (in days): 30 (リフレッシュトークンの有効期限は何日間?) 30 Do you want to specify the user attributes this app can read and write? No (このアプリが読み書きできるユーザを限定する?) No Do you want to enable any of the following capabilities? (Press <space> to select, <a> to toggle all, <i> to invert selection) Do you want to use an OAuth flow? No (OAuthは使用する??) No ? Do you want to configure Lambda Triggers for Cognito? No (Cognito用のLambdaトリガを設定する?) No
  9.   対話式ウィザードでバックエンドを簡単に作成できる   バックエンドにAPI機能を追加 10 Amplify CLI $ amplify add

    api ? Please select from one of the below mentioned services: GraphQL (APIの方式は?) GraphQL ? Provide API name: test (APIの名前は?) test ? Choose the default authorization type for the API Amazon Cognito User Pool (APIの認証方式は?) Amazon Cognito User Pool Use a Cognito user pool configured as a part of this project. ? Do you want to configure advanced settings for the GraphQL API No, I am done. (認証の設定を行う?) No, I am done. ? Do you have an annotated GraphQL schema? No (すでにGrapQLのスキーマを持ってる?) No ? Do you want a guided schema creation? No (サンプルのスキーマを作る?) No ? Provide a custom type name Test (スキーマタイプの名前は?) Test
  10. 11 AWS Amplify の機能   Amplifyの機能(カテゴリ)の例 機能名 フロントエンドAPI バックエンドカテゴリ AWSサービス

    内容 API APIClass api AppSync REST/GraphQLの利⽤ Authentication AuthClass auth Cognito 認証API XR XR xr Sumerian AR/VR Prediction prediction Recognition 機械学習 Notification PushNotification notifications Pinpoint プッシュ通知 Interactions Interactions interaction Lex Botの構築 Analytics AnalitycsClass analytics Pinpoint ユーザセッション等の計測 Hub HubClass ユーザセッション等の追跡 PubSub PubSub AWS IoT リアルタイムデータ Logger Logger コンソールログ I18n I18n 多⾔語化 hosting CloudFront 静的サイトホスティング
  11. 13 Amplify サンプルプロジェクトの全体図 バックエンドを⾃動デプロイ Amplify Console AppSync Cognito DynamoDB GraphQL

    コードの取得 Login ユーザ Webコンテンツ (Vue) 静的コンテンツ API 機能 Auth 機能 プロジェクトをfork (コピー) eijikominami/aws-amplify-samples
  12. 25 認証機能 Authenticater.Vue   認証画⾯ <amplify-authenticator> •  ユーザ登録 •  ログイン

    •  パスワード再発⾏ Main.Vue   メイン画⾯ •  ログインの有無をチェック •  ユーザ名の取得 Cognito   User Pool •  Email による ユーザログイン •  Email アドレス と 名前 の登録が必須 •  Email の認証が必要 •  Email による パスワードリセット •  Email の件名 と 本⽂をカスタマイズ –  認証コード をお送りします –  あなたの認証コードは {####} です。 バックエンド フロントエンド
  13. 26 認証機能のフロントエンド実装   Template   ログイン状態の確認   認証画⾯の表⽰ •  amplify-authenticator

    コンポーネントの利⽤ <template> <div id="authenticator"> <div v-if="signInStatus === 'signedOut'"> <amplify-authenticator v-bind:authConfig="authConfig"></amplify-authenticator> </div> </div> </template>
  14. 27 認証機能のフロントエンド実装   Script   ライブラリのインポート   認証画⾯の内容を設定 import {

    Auth } from 'aws-amplify' import { AmplifyEventBus } from 'aws-amplify-vue' data: function() { return { signInStatus: ' signedOut ' , authConfig: { usernameAttributes: ' Email ' , signUpConfig: { hideAllDefaults: true, signUpFields: [ { label: ' Email ' , key: ' email ' , required: true, displayOrder: 1, type: ' string ' , signUpWith: true }, ........   ログイン状態の確認 async beforeCreate() { try { await Auth.currentAuthenticatedUser() this.signInStatus = 'signedIn' router.push({path: '/'}) } catch (err) { this.signInStatus = 'signedOut' }
  15. 28 API機能 Main.Vue   データの追加 •  GraphQL Mutation クエリの実⾏ createChatMutation()

      データの表⽰ <amplify-connect> •  GraphQL Query クエリによる取得 listChatQuery () •  GraphQL Subscription クエリによる データ追加の検知と表⽰の⾃動更新 createChatSubscription() AppSync •  GraphQLスキーマの設定 •  DynamoDBのセットアップ •  Cognito によるユーザ認証 バックエンド フロントエンド type Chat @model @key(fields: ["userId", "createdAt"]) { userId: ID! createdAt: AWSTimestamp! name: String! message: String }
  16. 29 API機能のフロントエンド実装   Template   amplify-connect コンポーネントの利⽤ •  データ表⽰ <amplify-connect

    :query="listChatsQuery” :subscription="createChatSubscription" :onSubscriptionMsg="onCreateChat">> <template slot-scope="{loading, data, errors}"> <div v-if="loading">Loading...</div> <div v-else-if="errors.length > 0"></div> <div v-else-if="data"> <table class="table"> <thead> ... </thead> <tbody v-for="(item, index) in data.listChats.items" v-bind:key="item"> <tr> <th scope="row">{{ (index+1) }}</th> <td>{{ item.createdAt }}</td> <td>{{ item.name }}</td> <td>{{ item.message }}</td> </tr> </tbody> </table> </div> </template> </amplify-connect> •  データ⼊⼒ <amplify-connect :mutation="createChatMutation" @done="onCreateFinished"> <template slot-scope="{loading, mutate}"> <div class="input-group mb-3"> <div class="input-group-prepend"> <span class="input-group-text" id="message">Message</span> </div> <input v-model="chat.message" type="text" class="form-control" placeholder="your message here" aria-label="message" aria- describedby="message"> </div> <!-- ボタンクリック時に mutate メソッドを実行する --> <button type="button" class="btn btn- primary" :disabled="disableChatSubmitButton(loading)" @click="mutate">Save</button> </template> </amplify-connect>
  17. 30 API機能のフロントエンド実装   Script 関数 呼び出されるタイミング 実⾏内容 listChatsQuery 画⾯が表⽰されたとき 1. 

    listChat クエリ を実⾏してデータを取得 2.  画⾯にデータを表⽰ createChatSubscription 画⾯が表⽰されたとき 1.  onCreateChat サブスクリプション を実⾏ データの新規登録を検知する onCreateChat データの新規登録を検知したとき 1.  取得した新規データを既存のデータに追加 2.  画⾯が⾃動更新される createChatMutation SAVEボタンを押したとき 1.  createChat ミューテーションを実⾏ 2.  ⼊⼒したデータをサーバに送信 onCreateFinished データの送信が完了したとき 1.  ログを出⼒ mutate SAVEボタンを押したとき 1.  createChatMutation を実行
  18. 31 API機能のバックエンド定義 GraphQL スキーマ   扱うデータの種類とフィールドを定義   データ型の例 •  ID

    •  String •  Int •  Float •  Boolean •  AWSDate •  AWSTimestamp •  AWSJSON •  AWSURL type Chat @model @key(fields: ["userId", "createdAt"]) { userId: ID! createdAt: AWSTimestamp! name: String! message: String }   アノテーション アノテーション 内容 @model 最上位のエンティティ データは@model 単位でDynamoDB に格納される queries, mutations, subscriptions を⾃動⽣成 @key インデックスの指定 field: HASHキーおよびSORTキーを指定 name: セカンダリインデックスを指定
  19. 32 その他の機能の利⽤   国際化対応   I18n カテゴリを使⽤   認証画⾯を⽇本語化する  

    ロギング機能によるデバッグ   Logger カテゴリ let languageDict = { ja:{ 'Sign in to your account' : 'サインイン', 'Create a new account': 'アカウントの新規作成', 'Reset your password': 'パスワードをリセット', 'Confirm Sign Up': 'メールアドレスの認証', ......... } } AmplifyModules.I18n.putVocabularies(languageDict) import { Logger } from "aws-amplify" Logger.LOG_LEVEL = 'DEBUG'; const logger = new Logger('amplify-logger', 'INFO'); logger.info('hogehoge');
  20. 33 Amplify CLI   プロジェクトの作成と削除   バックエンドの作成と編集, 削除 コマンド 実⾏内容

    amplify init Amplify プロジェクトを作成/初期化, バックエンドの初期化 amplify delete Amplify プロジェクトを削除 コマンド 実⾏内容 amplify env add <ENV> バックエンドをプロジェクトに追加 amplify env remove <ENV> バックエンドをプロジェクトから削除 amplify env pull <ENV> --restore AWS上のバックエンド設定を参照してプロジェクトを上書き amplify env list バックエンドの⼀覧を表⽰
  21. 34 Amplify CLI   機能の追加   その他のコマンド コマンド 実⾏内容 amplify

    add <CATEGORY> プロジェクトに機能を追加 amplify update <CATEGORY> 既存の機能の設定を変更 amplify remove <CATEGORY> プロジェクトから機能を削除 コマンド 実⾏内容 amplify status プロジェクトの状態を表⽰ amplify push プロジェクトをAWS上でデプロイ amplify pull バックエンドをAWSから取得 amplify console Amplify Console を起動
  22. 37 ハンズオン②プロジェクトに機能を追加する   開発環境の構築   ソースコードのダウンロード   バックエンド設定を取得 git clone

    -b handson https://github.com/eijikominami/aws-amplify-samples.git cd aws-amplify-samples.git amplify pull --appId XXXXXXXX --envName handson
  23. 38 ハンズオン②プロジェクトに機能を追加する   開発環境の構築   バックエンド設定を取得(続き) $ amplify pull --appId

    XXXXXXXX --envName handson ? Do you want to use an AWS profile? Yes (AWSプロファイルを使用する?) Yes ? Please choose the profile you want to use default ? Which app are you working on? XXXXXXXX (どのアプケーション?) XXXXXXXX ? Pick a backend environment: handson (どのバックエンドを使用する?) handson ? Choose your default editor: Visual Studio Code (開発環境は?) Visual Studio Code ? Choose the type of app that you're building javascript (フロントエンドは?) javascript Please tell us about your project ? What javascript framework are you using vue (javascriptフレームワークは?) vue ? Source Directory Path: src ? Distribution Directory Path: dist ? Build Command: npm run-script build ? Start Command: npm run-script serve ? Do you plan on modifying this backend? No
  24. 39 ハンズオン②プロジェクトに機能を追加する   バックエンドの構築 GraphQLスキーマに追記 •  amplify/backend/api/threetierappsample/schema.graphql type Item @model

    @key(fields: ["itemId"]) { itemId: ID! status: Int! attributes: ItemAttribute date: ItemDate } type ItemAttribute { name: String description: String } type ItemDate { createdAt: AWSTimestamp! updatedAt: AWSTimestamp! }
  25. 40 ハンズオン②プロジェクトに機能を追加する   バックエンドの設定(続き) GraphQLスキーマをAWS上に反映 $ amplify push ✔ Successfully

    pulled backend environment handson from the cloud. | Category | Resource name | Operation | Provider plugin | | -------- | -------------------- | --------- | ----------------- | | Api | threetierappsample | Update | awscloudformation | | Auth | ThreeTierAppSamples | No Change | awscloudformation | | Auth | userPoolGroups | No Change | awscloudformation | | Api | AdminQueries | No Change | awscloudformation | | Function | AdminQueriesa150ebe9 | No Change | awscloudformation | ? Are you sure you want to continue? Yes GraphQL schema compiled successfully. Edit your schema at /Users/eiji/Documents/VisualStudioCode/test/aws-amplify-samples/amplify/backend/api/threetierappsample/ schema.graphql or place .graphql files in a directory at /Users/eiji/Documents/VisualStudioCode/test/aws-amplify-samples/amplify/ backend/api/threetierappsample/schema ? Do you want to update code for your updated GraphQL API Yes (GraphQL APIをアップデートする?) Yes ? Do you want to generate GraphQL statements (queries, mutations and subscription) based on your schema types? This will overwrite your current graphql queries, mutations and subscriptions Yes (GraphQL Queries, Mutations Subscriptionsを上書きする ?) Yes
  26. 41 ハンズオン②プロジェクトに機能を追加する   フロントエンドの構築   Templateにデータを⼊⼒するフォームを追加 <h3>Item List Sample</h3> <section>

    <amplify-connect :mutation="createItemMutation" @done="onCreateFinished"> <template slot-scope="{loading, mutate}"> <div class="input-group mb-3"> <div class="input-group-prepend"> <span class="input-group-text" id="message">Id</span> </div> <input v-model="item.itemId" type="text" class="form-control" placeholder="item id" aria-label="itemId" aria-describedby="itemId"> </div> <div class="input-group mb-3"> <div class="input-group-prepend"> <span class="input-group-text" id="message">Name</span> </div> <input v-model="item.attributes.name" type="text" class="form-control" placeholder="name" aria-label="name" aria-describedby="name"> </div> <div class="input-group mb-3"> <div class="input-group-prepend"> <label class="input-group-text" for="status">Status</label> </div> <select v-model="item.status" class="custom-select" id="status"> <option value="1">True</option> <option value="0">False</option> </select> </div> <div class="input-group mb-3"> <div class="input-group-prepend"> <span class="input-group-text" id="message">Description</span> </div> <input v-model="item.attributes.description" type="text" class="form-control" placeholder="description" aria-label="description" aria-describedby="description"> </div> <button type="button" class="btn btn-primary" :disabled="disableItemListSubmitButton(loading)" @click="mutate">Save</button> </template> </amplify-connect> </section>
  27. 42 ハンズオン②プロジェクトに機能を追加する   フロントエンドの構築   Templateにデータを表⽰するテーブルを追加 <section> <amplify-connect :query="listItemsQuery" :subscription="createItemSubscription"

    :onSubscriptionMsg="onCreateItem">> <template slot-scope="{loading, data, errors}"> <div v-if="loading">Loading...</div> <div v-else-if="errors.length > 0"></div> <div v-else-if="data"> <table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">Item Id</th> <th scope="col">Name</th> <th scope="col">Updated At</th> <th scope="col">Status</th> <th scope="col">Change status</th> <th scope="col">Created At</th> <th scope="col">Description</th> <th scope="col">Delete</th> </tr> </thead> <tbody v-for="(item, index) in data.listItems.items" v-bind:key="item"> <tr> <th scope="row">{{ (index+1) }}</th> <td>{{ item.itemId }}</td> <td>{{ item.attributes.name }}</td> <td>{{ item.date.updatedAt }}</td> <td>{{ item.status }}</td> <td><button type="button" class="btn btn-primary" @click="updateItemMutation(item.itemId, item.date.createdAt, item.status)">Change status</button></td> <td>{{ item.date.createdAt }}</td> <td>{{ item.attributes.description }}</td> <td><button type="button" class="btn btn-primary" @click="deleteItemMutation(item.itemId)">Delete</button></td> </tr> </tbody> </table> </div> </template> </amplify-connect> </section>
  28. 43 ハンズオン②プロジェクトに機能を追加する   フロントエンドの構築   ライブラリを追加   Scriptにクエリの定義を追加 const ListItemsQuery

    = `query ListItems { listItems { items { itemId status attributes { name description } date { createdAt updatedAt } } } }`; import { Auth, API, graphqlOperation } from "aws-amplify"
  29. 44 ハンズオン②プロジェクトに機能を追加する   フロントエンドの構築   computed に関数を追加 updateItemMutation: function() {

    return function(itemId, createdAt, prevStatus) { var date = new Date() ; var updatedAt = date.getTime() ; return API.graphql(graphqlOperation(mutations.updateItem, {input: { itemId: itemId, status: (prevStatus === 1) ? 0 : 1, date: { createdAt: createdAt, updatedAt: updatedAt } } })); } }, deleteItemMutation: function() { return function(itemId) { return API.graphql(graphqlOperation(mutations.deleteItem, {input: { itemId: itemId } })); } }, disableItemListSubmitButton: function() { return function(loading) { return loading || !this.item.itemId || !this.item.attributes.name || !this.item.attributes.description; } },
  30. 45 ハンズオン②プロジェクトに機能を追加する   フロントエンドの構築   computed に関数を追加(続き) createItemMutation() { var

    date = new Date() ; var createdAt = date.getTime() ; return this.$Amplify.graphqlOperation(mutations.createItem, {input: { itemId: this.item.itemId, status: this.item.status, attributes: { name: this.item.attributes.name, description: this.item.attributes.description }, date: { createdAt: createdAt, updatedAt: createdAt } } }); }, listItemsQuery() { return this.$Amplify.graphqlOperation(ListItemsQuery); }, createItemSubscription() { return this.$Amplify.graphqlOperation(subscriptions.onCreateItem); }
  31. 46 ハンズオン②プロジェクトに機能を追加する   フロントエンドの構築   methods に関数を追加   プロジェクトをGitHubにPush  

    ⾃動的にAmplify Consoleのデプロイが開始される onCreateItem(prevData, newData) { const newItem = newData.onCreateItem; prevData.data.listItems.items.push(newItem); return prevData.data; } git push origin handson