「AWS Hands-on for Beginners AWS Amplify を用いた Web サイトの構築方法を学ぼう」をAWS CLIでやってみる

https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-amplify-2022-reg-event.html?trk=aws_introduction_page

上記、「AWS Hands-on for Beginners AWS Amplify を用いた Web サイトの構築方法を学ぼう」 をAWS CLIでやってみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/37f90f5a-186e-22c8-6ab7-1046cdb3cc20.png)
ハンズオンから引用

:::note alert
Cloud9は新規利用できなくなりました。
今まで利用したことがあるアカウントはまだ利用できるようです。
:::

# 02 AWS Amplify のハンズオン（環境構築、Cloud9 編）
## Cloud9環境構築
### Cloud9環境構築 (CloudShellで実施)
```bash:コマンド
# Cloud9環境名
CLOUD9_ENVIRONMENT_NAME="handson" \
&& echo ${CLOUD9_ENVIRONMENT_NAME}

# インスタンスタイプ
CLOUD9_INSTANCE_TYPE="t3.small" \
&& echo ${CLOUD9_INSTANCE_TYPE}

# プラットフォーム
CLOUD9_IMAGE_ID="resolve:ssm:/aws/service/cloud9/amis/amazonlinux-2-x86_64" \
&& echo ${CLOUD9_IMAGE_ID}

# Cloud9環境作成
CLOUD9_ENVIRONMENT_ID=$(
    aws cloud9 create-environment-ec2 \
        --name ${CLOUD9_ENVIRONMENT_NAME} \
        --instance-type ${CLOUD9_INSTANCE_TYPE} \
        --image-id ${CLOUD9_IMAGE_ID} \
        --connection-type CONNECT_SSM \
        --automatic-stop-time-minutes 30 \
        --query environmentId \
        --output text
) \
&& echo ${CLOUD9_ENVIRONMENT_ID}

```
```bash:出力
[cloudshell-user@ip-10-132-68-36 ~]$ # Cloud9環境名
[cloudshell-user@ip-10-132-68-36 ~]$ CLOUD9_ENVIRONMENT_NAME="handson" \
> && echo ${CLOUD9_ENVIRONMENT_NAME}
handson
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # インスタンスタイプ
[cloudshell-user@ip-10-132-68-36 ~]$ CLOUD9_INSTANCE_TYPE="t3.small" \
> && echo ${CLOUD9_INSTANCE_TYPE}
t3.small
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # プラットフォーム
[cloudshell-user@ip-10-132-68-36 ~]$ CLOUD9_IMAGE_ID="resolve:ssm:/aws/service/cloud9/amis/amazonlinux-2-x86_64" \
> && echo ${CLOUD9_IMAGE_ID}
resolve:ssm:/aws/service/cloud9/amis/amazonlinux-2-x86_64
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # Cloud9環境作成
[cloudshell-user@ip-10-132-68-36 ~]$ CLOUD9_ENVIRONMENT_ID=$(
>     aws cloud9 create-environment-ec2 \
>         --name ${CLOUD9_ENVIRONMENT_NAME} \
>         --instance-type ${CLOUD9_INSTANCE_TYPE} \
>         --image-id ${CLOUD9_IMAGE_ID} \
>         --connection-type CONNECT_SSM \
>         --automatic-stop-time-minutes 30 \
>         --query environmentId \
>         --output text
> ) \
> && echo ${CLOUD9_ENVIRONMENT_ID}
04fe8f6beae044f088baf19dfc89bef8
```
### クレデンシャル無効化 (CloudShellで実施)
```bash:コマンド
aws cloud9 update-environment \
    --environment-id ${CLOUD9_ENVIRONMENT_ID} \
    --managed-credentials-action DISABLE

```
```bash:出力
[cloudshell-user@ip-10-132-68-36 ~]$ aws cloud9 update-environment \
>     --environment-id ${CLOUD9_ENVIRONMENT_ID} \
>     --managed-credentials-action DISABLE
```
## EC2ストレージ容量拡張
### ファイルシステムの確認 (Cloud9で実施)
```bash:コマンド
# 容量の確認
df -h

# ファイルシステムの確認
df -Th /

# パーティション確認
lsblk

```
```bash:出力
admin:~/environment $ # 容量の確認
admin:~/environment $ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        953M     0  953M   0% /dev
tmpfs           963M     0  963M   0% /dev/shm
tmpfs           963M  468K  962M   1% /run
tmpfs           963M     0  963M   0% /sys/fs/cgroup
/dev/nvme0n1p1   10G  5.8G  4.3G  58% /
tmpfs           193M     0  193M   0% /run/user/1000
admin:~/environment $ 
admin:~/environment $ # ファイルシステムの確認
admin:~/environment $ df -Th /
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme0n1p1 xfs    10G  5.8G  4.3G  58% /
admin:~/environment $ 
admin:~/environment $ # パーティション確認
admin:~/environment $ lsblk
NAME          MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1       259:0    0  10G  0 disk 
├─nvme0n1p1   259:1    0  10G  0 part /
└─nvme0n1p128 259:2    0   1M  0 part 
```
### EC2ストレージ容量拡張 (CloudShellで実施)
```bash:コマンド
# インスタンスのボリュームID確認
EC2_VOLUME_ID=$(
    aws ec2 describe-instances \
        --filters "Name=tag:Name,Values=aws-cloud9-${CLOUD9_ENVIRONMENT_NAME}-${CLOUD9_ENVIRONMENT_ID}" \
        --query 'Reservations[*].Instances[*].[BlockDeviceMappings[*].Ebs.VolumeId]' \
        --output text
) \
&& echo ${EC2_VOLUME_ID}

# EBSボリュームのサイズを変更
aws ec2 modify-volume \
    --volume-id ${EC2_VOLUME_ID} \
    --size 32

```
```bash:出力
[cloudshell-user@ip-10-132-68-36 ~]$ # インスタンスのボリュームID確認
[cloudshell-user@ip-10-132-68-36 ~]$ EC2_VOLUME_ID=$(
>     aws ec2 describe-instances \
>         --filters "Name=tag:Name,Values=aws-cloud9-${CLOUD9_ENVIRONMENT_NAME}-${CLOUD9_ENVIRONMENT_ID}" \
>         --query 'Reservations[*].Instances[*].[BlockDeviceMappings[*].Ebs.VolumeId]' \
>         --output text
> ) \
> && echo ${EC2_VOLUME_ID}
vol-0e9aec950c9647239
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # EBSボリュームのサイズを変更
[cloudshell-user@ip-10-132-68-36 ~]$ aws ec2 modify-volume \
>     --volume-id ${EC2_VOLUME_ID} \
>     --size 32
{
    "VolumeModification": {
        "VolumeId": "vol-0e9aec950c9647239",
        "ModificationState": "modifying",
        "TargetSize": 32,
        "TargetIops": 3000,
        "TargetVolumeType": "gp3",
        "TargetThroughput": 125,
        "TargetMultiAttachEnabled": false,
        "OriginalSize": 10,
        "OriginalIops": 3000,
        "OriginalVolumeType": "gp3",
        "OriginalThroughput": 125,
        "OriginalMultiAttachEnabled": false,
        "Progress": 0,
        "StartTime": "2024-10-12T11:57:17+00:00"
    }
}
```
### ファイルシステム拡張 (Cloud9で実施)
```bash:コマンド
# パーティションを拡張
sudo growpart /dev/nvme0n1 1

# ファイルシステムを拡張 (XFSの場合)
sudo xfs_growfs -d /

# 容量の確認
df -h

```
```bash:出力
admin:~/environment $ # パーティションを拡張
admin:~/environment $ sudo growpart /dev/nvme0n1 1
CHANGED: partition=1 start=4096 old: size=20967391 end=20971487 new: size=67104735 end=67108831
admin:~/environment $ 
admin:~/environment $ # ファイルシステムを拡張 (XFSの場合)
admin:~/environment $ sudo xfs_growfs -d /
meta-data=/dev/nvme0n1p1         isize=512    agcount=6, agsize=524159 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=0, rmapbt=0
         =                       reflink=0    bigtime=0 inobtcount=0
data     =                       bsize=4096   blocks=2620923, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 2620923 to 8388091
admin:~/environment $ 
admin:~/environment $ # 容量の確認
admin:~/environment $ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        953M     0  953M   0% /dev
tmpfs           963M     0  963M   0% /dev/shm
tmpfs           963M  456K  962M   1% /run
tmpfs           963M     0  963M   0% /sys/fs/cgroup
/dev/nvme0n1p1   32G  5.8G   27G  19% /
tmpfs           193M     0  193M   0% /run/user/1000
```
# 03 AWS Amplify のハンズオン（環境構築、CLI 編）
https://docs.amplify.aws/gen1/react/start/getting-started/installation/
## Amplify用ユーザーの作成 (CloudShellで実施)
```bash:コマンド
# ユーザー名
USER_NAME="amplify-dev " \
&& echo ${USER_NAME}

# ポリシー名
POLICY_NAME="AdministratorAccess-Amplify" \
&& echo ${POLICY_NAME}

# ユーザー作成
aws iam create-user --user-name ${USER_NAME}

# ポリシーのアタッチ
aws iam attach-user-policy \
    --user-name ${USER_NAME} \
    --policy-arn arn:aws:iam::aws:policy/${POLICY_NAME}

# アクセスキーの作成
aws iam create-access-key --user-name ${USER_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-68-36 ~]$ # ユーザー名
[cloudshell-user@ip-10-132-68-36 ~]$ USER_NAME="amplify-dev " \
> && echo ${USER_NAME}
amplify-dev
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # ポリシー名
[cloudshell-user@ip-10-132-68-36 ~]$ POLICY_NAME="AdministratorAccess-Amplify" \
> && echo ${POLICY_NAME}
AdministratorAccess-Amplify
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # ユーザー作成
[cloudshell-user@ip-10-132-68-36 ~]$ aws iam create-user --user-name ${USER_NAME}
{
    "User": {
        "Path": "/",
        "UserName": "amplify-dev",
        "UserId": "AIDAWFKRCMKO6LDGRI7LL",
        "Arn": "arn:aws:iam::999999999999:user/amplify-dev",
        "CreateDate": "2024-10-12T11:58:02+00:00"
    }
}
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # ポリシーのアタッチ
[cloudshell-user@ip-10-132-68-36 ~]$ aws iam attach-user-policy \
>     --user-name ${USER_NAME} \
>     --policy-arn arn:aws:iam::aws:policy/${POLICY_NAME}
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # アクセスキーの作成
[cloudshell-user@ip-10-132-68-36 ~]$ aws iam create-access-key --user-name ${USER_NAME}
{
    "AccessKey": {
        "UserName": "amplify-dev",
        "AccessKeyId": "********************",
        "Status": "Active",
        "SecretAccessKey": "****************************************",
        "CreateDate": "2024-10-12T11:58:07+00:00"
    }
}
```
:::note info
以降、Cloud9で実施
:::
## Node.js 環境のセットアップ（インスタンスにインストール済み）
```bash:コマンド
node -v

```
```bash:出力
admin:~/environment $ node -v
v18.20.2
```
## Amplify CLI のインストールとセットアップ
### Amplify CLI のインストール
```bash:コマンド
npm install -g @aws-amplify/cli

```
```bash:出力
admin:~/environment $ npm install -g @aws-amplify/cli
npm error code EACCES
npm error syscall mkdir
npm error path /usr/local/nodejs/v18.20.2/lib/node_modules/@aws-amplify
npm error errno -13
npm error [Error: EACCES: permission denied, mkdir '/usr/local/nodejs/v18.20.2/lib/node_modules/@aws-amplify'] {
npm error   errno: -13,
npm error   code: 'EACCES',
npm error   syscall: 'mkdir',
npm error   path: '/usr/local/nodejs/v18.20.2/lib/node_modules/@aws-amplify'
npm error }
npm error
npm error The operation was rejected by your operating system.
npm error It is likely you do not have the permissions to access this file as the current user
npm error
npm error If you believe this might be a permissions issue, please double-check the
npm error permissions of the file and its containing directories, or try running
npm error the command again as root/Administrator.
npm error A complete log of this run can be found in: /home/ec2-user/.npm/_logs/2024-10-12T11_58_35_584Z-debug-0.log
```
:::note alert
ACCESエラーになるので下記を実施
https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally
:::
### npmのデフォルトディレクトリを手動で変更する
#### インストール用のディレクトリを作成
```bash:コマンド
mkdir -p ~/.npm-global/lib

```
```bash:出力
admin:~/environment $ mkdir -p ~/.npm-global/lib
```
#### インストール用のディレクトリを作成
```bash:コマンド
mkdir -p ~/.npm-global/lib

```
```bash:出力
admin:~/environment $ mkdir -p ~/.npm-global/lib
```
#### 新しいディレクトリ パスを使用するように npm を構成
```bash:コマンド
npm config set prefix '~/.npm-global'

```
```bash:出力
admin:~/environment $ npm config set prefix '~/.npm-global'
```
#### ~/.profileを更新
```bash:コマンド
cat << "EOF" >> ~/.profile
export PATH=~/.npm-global/bin:$PATH
EOF

```
```bash:出力
admin:~/environment $ cat << "EOF" >> ~/.profile
> export PATH=~/.npm-global/bin:$PATH
> EOF
```
#### システム変数を更新
```bash:コマンド
source ~/.profile

```
```bash:出力
admin:~/environment $ source ~/.profile
```
#### 新しい設定をテスト
```bash:コマンド
npm install -g jshint

```
```bash:出力
admin:~/environment $ npm install -g jshint
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported

added 31 packages in 5s

3 packages are looking for funding
  run `npm fund` for details
```
### Amplify CLI の再インストール
```bash:コマンド
npm install -g @aws-amplify/cli

```
```bash:出力
admin:~/environment $ npm install -g @aws-amplify/cli
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported

added 33 packages in 16s

7 packages are looking for funding
  run `npm fund` for details
```
### Amplify CLIを設定
```bash:コマンド
amplify configure

```
```bash:出力
admin:~/environment $ amplify configure
Follow these steps to set up access to your AWS account:

Sign in to your AWS administrator account:
https://console.aws.amazon.com/
Press Enter to continue
Unable to open https://console.aws.amazon.com/: spawn xdg-open ENOENT
Have you installed `xdg-utils` on your machine?
^C
^Aborted!
```
:::note alert
xdg-utilsがインストールされていないのでエラーになる
:::
#### xdg-utilsのインストール
```bash:コマンド
sudo yum -y install xdg-utils

```
```bash:出力
admin:~/environment $ sudo yum -y install xdg-utils
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
237 packages excluded due to repository priority protections
Resolving Dependencies
--> Running transaction check
---> Package xdg-utils.noarch 0:1.1.0-0.17.20120809git.amzn2.0.1 will be installed
--> Processing Dependency: desktop-file-utils for package: xdg-utils-1.1.0-0.17.20120809git.amzn2.0.1.noarch
--> Running transaction check
---> Package desktop-file-utils.x86_64 0:0.23-2.amzn2 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

====================================================================================================================================================================================================================================================
 Package                                                     Arch                                            Version                                                                      Repository                                           Size
====================================================================================================================================================================================================================================================
Installing:
 xdg-utils                                                   noarch                                          1.1.0-0.17.20120809git.amzn2.0.1                                             amzn2-core                                           70 k
Installing for dependencies:
 desktop-file-utils                                          x86_64                                          0.23-2.amzn2                                                                 amzn2-core                                           68 k

Transaction Summary
====================================================================================================================================================================================================================================================
Install  1 Package (+1 Dependent package)

Total download size: 138 k
Installed size: 474 k
Downloading packages:
(1/2): desktop-file-utils-0.23-2.amzn2.x86_64.rpm                                                                                                                                                                            |  68 kB  00:00:00     
(2/2): xdg-utils-1.1.0-0.17.20120809git.amzn2.0.1.noarch.rpm                                                                                                                                                                 |  70 kB  00:00:00     
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                                                                                               1.0 MB/s | 138 kB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : desktop-file-utils-0.23-2.amzn2.x86_64                                                                                                                                                                                           1/2 
  Installing : xdg-utils-1.1.0-0.17.20120809git.amzn2.0.1.noarch                                                                                                                                                                                2/2 
  Verifying  : xdg-utils-1.1.0-0.17.20120809git.amzn2.0.1.noarch                                                                                                                                                                                1/2 
  Verifying  : desktop-file-utils-0.23-2.amzn2.x86_64                                                                                                                                                                                           2/2 

Installed:
  xdg-utils.noarch 0:1.1.0-0.17.20120809git.amzn2.0.1                                                                                                                                                                                               

Dependency Installed:
  desktop-file-utils.x86_64 0:0.23-2.amzn2                                                                                                                                                                                                          

Complete!
```
### Amplify CLIを再設定
```bash:コマンド
amplify configure

```
```bash:出力
admin:~/environment $ amplify configure
Follow these steps to set up access to your AWS account:

Sign in to your AWS administrator account:
https://console.aws.amazon.com/
Press Enter to continue

Specify the AWS Region
? region:  ap-northeast-1
Follow the instructions at
https://docs.amplify.aws/cli/start/install/#configure-the-amplify-cli

to complete the user creation in the AWS console
https://console.aws.amazon.com/iamv2/home#/users/create
Press Enter to continue

Enter the access key of the newly created user:
? accessKeyId:  ********************
? secretAccessKey:  ****************************************
This would update/create the AWS Profile in your local machine
? Profile Name:  default

Successfully set up the new user.
```
## Reactアプリの作成
https://docs.amplify.aws/gen1/react/start/getting-started/setup/

:::note warn
現在の公式手順は上記リンク先になりハンズオンの手順と異なる。しかし、現在の公式手順では動作確認時のローカルサーバの起動ポート番号の変更ができず、Cloud9のPreview機能での動作確認ができなかったのでハンズオンの手順のまま実施
:::
### Reactアプリの作成
```bash:コマンド
npx create-react-app react-amplified

```
```bash:出力
admin:~/environment $ npx create-react-app react-amplified
Need to install the following packages:
create-react-app@5.0.1
Ok to proceed? (y) y

npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated rimraf@2.7.1: Rimraf versions prior to v4 are no longer supported
npm warn deprecated uid-number@0.0.6: This package is no longer supported.
npm warn deprecated fstream-ignore@1.0.5: This package is no longer supported.
npm warn deprecated fstream@1.0.12: This package is no longer supported.
npm warn deprecated tar@2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.

Creating a new React app in /home/ec2-user/environment/react-amplified.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template...


added 1478 packages in 2m

262 packages are looking for funding
  run `npm fund` for details

Initialized a git repository.

Installing template dependencies using npm...

added 63 packages, and changed 1 package in 24s

262 packages are looking for funding
  run `npm fund` for details
Removing template package using npm...


removed 1 package, and audited 1541 packages in 15s

262 packages are looking for funding
  run `npm fund` for details

8 vulnerabilities (2 moderate, 6 high)

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

Created git commit.

Success! Created react-amplified at /home/ec2-user/environment/react-amplified
Inside that directory, you can run several commands:

  npm start
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd react-amplified
  npm start

Happy hacking!
```
### ディレクトリ移動
```bash:コマンド
cd react-amplified

```
```bash:出力
admin:~/environment $ cd react-amplified
admin:~/environment/react-amplified (master) $ 
```
### 動作確認
```bash:コマンド
npm start

```
```bash:出力
Compiled successfully!

You can now view react-amplified in the browser.

  Local:            http://localhost:8080
  On Your Network:  http://172.31.6.39:8080

Note that the development build is not optimized.
To create a production build, use npm run build.

webpack compiled successfully
```
Preview > Preview Running Applicationから表示確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/32825abb-b36b-1508-aa50-cbe6e8b5cb10.png)
## Amplify Project の初期化コマンド
```bash:コマンド
amplify init

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify init
⚠️ For new projects, we recommend starting with AWS Amplify Gen 2, our new code-first developer experience. Get started at https://docs.amplify.aws/react/start/quickstart/
✔ Do you want to continue with Amplify Gen 1? (y/N) · yes
✔ Why would you like to use Amplify Gen 1? · Prefer not to answer
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project reactamplified
The following configuration will be applied:

Project information
| Name: reactamplified
| 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

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS profile

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Please choose the profile you want to use default
Adding backend environment dev to AWS Amplify app: d14fd37vg009fk

Deployment completed.
Deploying root stack reactamplified [ ==========------------------------------ ] 1/4
        amplify-reactamplified-dev-54… AWS::CloudFormation::Stack     CREATE_IN_PROGRESS             Sat Oct 12 2024 12:14:41…     
        UnauthRole                     AWS::IAM::Role                 CREATE_IN_PROGRESS             Sat Oct 12 2024 12:14:43…     
        AuthRole                       AWS::IAM::Role                 CREATE_IN_PROGRESS             Sat Oct 12 2024 12:14:43…     
        DeploymentBucket               AWS::S3::Bucket                CREATE_COMPLETE                Sat Oct 12 2024 12:14:59…     

✔ Help improve Amplify CLI by sharing non-sensitive project configurations on failures (y/N) · no

    You can always opt-in by running "amplify configure --share-project-config-on"
Deployment state saved successfully.
✔ Initialized provider successfully.
✅ Initialized your environment successfully.
✅ Your project has been successfully initialized and connected to the cloud!
Some next steps:

"amplify status" will show you what you've added already and if it's locally configured or deployed
"amplify add <category>" will allow you to add features like user login or a backend API
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify console" to open the Amplify Console and view your project status
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud


Pro tip:
Try "amplify add api" to create a backend API and then "amplify push" to deploy everything
```
## Amplify Framework のインストール
```bash:コマンド
npm install aws-amplify @aws-amplify/ui-react

```
```bash:出力
admin:~/environment/react-amplified (master) $ npm install aws-amplify @aws-amplify/ui-react

added 290 packages, and audited 1831 packages in 2m

270 packages are looking for funding
  run `npm fund` for details

8 vulnerabilities (2 moderate, 6 high)

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
```
## フロントエンドの設定
```bash:コマンド
cat << EOF > src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import { Amplify } from 'aws-amplify';
import amplifyconfig from './amplifyconfiguration.json';
Amplify.configure(amplifyconfig);

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// 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();
EOF

```
```bash:出力
admin:~/environment/react-amplified (master) $ cat << EOF > src/index.js
> import React from 'react';
> import ReactDOM from 'react-dom/client';
> import './index.css';
> import App from './App';
> import reportWebVitals from './reportWebVitals';
> 
> import { Amplify } from 'aws-amplify';
> import amplifyconfig from './amplifyconfiguration.json';
> Amplify.configure(amplifyconfig);
> 
> const root = ReactDOM.createRoot(document.getElementById('root'));
> root.render(
>   <React.StrictMode>
>     <App />
>   </React.StrictMode>
> );
> 
> // 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();
> EOF
```
# 04 AWS Amplify のハンズオン（FE/API/DB 編）
https://docs.amplify.aws/gen1/react/start/getting-started/data-model/
## Amplify CLI で API の追加
```bash:コマンド
amplify add api

```
```bash:出力
admin:~/environment/react-amplified (master) $ 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 /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema
✔ Do you want to edit the schema now? (Y/n) · no
✅ Successfully added resource reactamplified 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
```
## AWS への反映
### 現状のAmplify上リソースの状態確認
```bash:コマンド
amplify status

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify status

    Current Environment: dev
    
┌──────────┬────────────────┬───────────┬───────────────────┐
│ Category │ Resource name  │ Operation │ Provider plugin   │
├──────────┼────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified │ Create    │ awscloudformation │
└──────────┴────────────────┴───────────┴───────────────────┘

GraphQL transformer version: 2
```
### AWS への反映
```bash:コマンド
amplify push

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify push
⠼ Fetching updates to backend environment: dev from the cloud.⠋ Building resource api/reactamplified
⚠️  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

⠹ Building resource api/reactamplified✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema
✔ Successfully pulled backend environment dev from the cloud.
⠋ Building resource api/reactamplified
⚠️  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

⠸ Building resource api/reactamplified✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema

    Current Environment: dev
    
┌──────────┬────────────────┬───────────┬───────────────────┐
│ Category │ Resource name  │ Operation │ Provider plugin   │
├──────────┼────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified │ Create    │ awscloudformation │
└──────────┴────────────────┴───────────┴───────────────────┘
✔ Are you sure you want to continue? (Y/n) · 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 /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema
⠋ Building resource api/reactamplified
⚠️  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

⠸ Building resource api/reactamplified✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/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

Deployment completed.
Deploying root stack reactamplified [ ---------------------------------------- ] 0/2
        amplify-reactamplified-dev-54… AWS::CloudFormation::Stack     UPDATE_IN_PROGRESS             Sat Oct 12 2024 12:32:20…     
        apireactamplified              AWS::CloudFormation::Stack     CREATE_IN_PROGRESS             Sat Oct 12 2024 12:32:23…     
Deploying api reactamplified [ =================================------- ] 5/6
        GraphQLAPI                     AWS::AppSync::GraphQLApi       CREATE_COMPLETE                Sat Oct 12 2024 12:32:29…     
        GraphQLAPINONEDS95A13CF0       AWS::AppSync::DataSource       CREATE_COMPLETE                Sat Oct 12 2024 12:32:31…     
        GraphQLAPITransformerSchema3C… AWS::AppSync::GraphQLSchema    CREATE_COMPLETE                Sat Oct 12 2024 12:32:33…     
        GraphQLAPIDefaultApiKey215A6D… AWS::AppSync::ApiKey           CREATE_COMPLETE                Sat Oct 12 2024 12:32:31…     
        Todo                           AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Oct 12 2024 12:33:21…     
        CustomResourcesjson            AWS::CloudFormation::Stack     CREATE_IN_PROGRESS             Sat Oct 12 2024 12:33:22…     

✔ Generated GraphQL operations successfully and saved at src/graphql
Deployment state saved successfully.

GraphQL endpoint: https://5dn6xw5cfreunflz64dma2lizm.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: da2-jntwjassfzcwbd2ave47jjss4m

GraphQL transformer version: 2
```
## srcコードの変更
:::note warn
srcコードは下記、公式ドキュメントを参照
https://docs.amplify.aws/gen1/react/start/getting-started/data-model/
:::
```bash:コマンド
cat << EOF > src/App.js
import { useEffect, useState } from 'react';

import { generateClient } from 'aws-amplify/api';

import { createTodo } from './graphql/mutations';
import { listTodos } from './graphql/queries';

const initialState = { name: '', description: '' };
const client = generateClient();

const App = () => {
  const [formState, setFormState] = useState(initialState);
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    fetchTodos();
  }, []);

  function setInput(key, value) {
    setFormState({ ...formState, [key]: value });
  }

  async function fetchTodos() {
    try {
      const todoData = await client.graphql({
        query: listTodos
      });
      const todos = todoData.data.listTodos.items;
      setTodos(todos);
    } catch (err) {
      console.log('error fetching todos');
    }
  }

  async function addTodo() {
    try {
      if (!formState.name || !formState.description) return;
      const todo = { ...formState };
      setTodos([...todos, todo]);
      setFormState(initialState);
      await client.graphql({
        query: createTodo,
        variables: {
          input: todo
        }
      });
    } catch (err) {
      console.log('error creating todo:', err);
    }
  }

  return (
    <div style={styles.container}>
      <h2>Amplify Todos</h2>
      <input
        onChange={(event) => setInput('name', event.target.value)}
        style={styles.input}
        value={formState.name}
        placeholder="Name"
      />
      <input
        onChange={(event) => setInput('description', event.target.value)}
        style={styles.input}
        value={formState.description}
        placeholder="Description"
      />
      <button style={styles.button} onClick={addTodo}>
        Create Todo
      </button>
      {todos.map((todo, index) => (
        <div key={todo.id ? todo.id : index} style={styles.todo}>
          <p style={styles.todoName}>{todo.name}</p>
          <p style={styles.todoDescription}>{todo.description}</p>
        </div>
      ))}
    </div>
  );
};

const styles = {
  container: {
    width: 400,
    margin: '0 auto',
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    padding: 20
  },
  todo: { marginBottom: 15 },
  input: {
    border: 'none',
    backgroundColor: '#ddd',
    marginBottom: 10,
    padding: 8,
    fontSize: 18
  },
  todoName: { fontSize: 20, fontWeight: 'bold' },
  todoDescription: { marginBottom: 0 },
  button: {
    backgroundColor: 'black',
    color: 'white',
    outline: 'none',
    fontSize: 18,
    padding: '12px 0px'
  }
};

export default App;
EOF

```
```bash:出力
admin:~/environment/react-amplified (master) $ cat << EOF > src/App.js
> import { useEffect, useState } from 'react';
> 
> import { generateClient } from 'aws-amplify/api';
> 
> import { createTodo } from './graphql/mutations';
> import { listTodos } from './graphql/queries';
> 
> const initialState = { name: '', description: '' };
> const client = generateClient();
> 
> const App = () => {
>   const [formState, setFormState] = useState(initialState);
>   const [todos, setTodos] = useState([]);
> 
>   useEffect(() => {
>     fetchTodos();
>   }, []);
> 
>   function setInput(key, value) {
>     setFormState({ ...formState, [key]: value });
>   }
> 
>   async function fetchTodos() {
>     try {
>       const todoData = await client.graphql({
>         query: listTodos
>       });
>       const todos = todoData.data.listTodos.items;
>       setTodos(todos);
>     } catch (err) {
>       console.log('error fetching todos');
>     }
>   }
> 
>   async function addTodo() {
>     try {
>       if (!formState.name || !formState.description) return;
>       const todo = { ...formState };
>       setTodos([...todos, todo]);
>       setFormState(initialState);
>       await client.graphql({
>         query: createTodo,
>         variables: {
>           input: todo
>         }
>       });
>     } catch (err) {
>       console.log('error creating todo:', err);
>     }
>   }
> 
>   return (
>     <div style={styles.container}>
>       <h2>Amplify Todos</h2>
>       <input
>         onChange={(event) => setInput('name', event.target.value)}
>         style={styles.input}
>         value={formState.name}
>         placeholder="Name"
>       />
>       <input
>         onChange={(event) => setInput('description', event.target.value)}
>         style={styles.input}
>         value={formState.description}
>         placeholder="Description"
>       />
>       <button style={styles.button} onClick={addTodo}>
>         Create Todo
>       </button>
>       {todos.map((todo, index) => (
>         <div key={todo.id ? todo.id : index} style={styles.todo}>
>           <p style={styles.todoName}>{todo.name}</p>
>           <p style={styles.todoDescription}>{todo.description}</p>
>         </div>
>       ))}
>     </div>
>   );
> };
> 
> const styles = {
>   container: {
>     width: 400,
>     margin: '0 auto',
>     display: 'flex',
>     flexDirection: 'column',
>     justifyContent: 'center',
>     padding: 20
>   },
>   todo: { marginBottom: 15 },
>   input: {
>     border: 'none',
>     backgroundColor: '#ddd',
>     marginBottom: 10,
>     padding: 8,
>     fontSize: 18
>   },
>   todoName: { fontSize: 20, fontWeight: 'bold' },
>   todoDescription: { marginBottom: 0 },
>   button: {
>     backgroundColor: 'black',
>     color: 'white',
>     outline: 'none',
>     fontSize: 18,
>     padding: '12px 0px'
>   }
> };
> 
> export default App;
> EOF
```
## 動作確認
```bash:コマンド
npm start

```
```bash:出力
Compiled successfully!

You can now view react-amplified in the browser.

  Local:            http://localhost:8080
  On Your Network:  http://172.31.6.39:8080

Note that the development build is not optimized.
To create a production build, use npm run build.

webpack compiled successfully
```
Preview > Preview Running Applicationから表示確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/948105ed-44d7-eec2-d023-f79c51756eef.png)
# 05 AWS Amplify のハンズオン（Auth 編）
https://docs.amplify.aws/gen1/react/start/getting-started/auth/
## Amplify CLI で Auth の追加
```bash:コマンド
amplify add auth

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify add auth
Using service: Cognito, provided by: awscloudformation
 
 The current configured provider is Amazon Cognito. 
 
 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Username
 Do you want to configure advanced settings? No, I am done.
✅ Successfully added auth resource reactamplified8f10cd21 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
```
## AWS へ反映
### 現状のAmplify上リソースの状態確認
```bash:コマンド
amplify status

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify status

    Current Environment: dev
    
┌──────────┬────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name          │ Operation │ Provider plugin   │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Auth     │ reactamplified8f10cd21 │ Create    │ awscloudformation │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified         │ No Change │ awscloudformation │
└──────────┴────────────────────────┴───────────┴───────────────────┘

GraphQL endpoint: https://5dn6xw5cfreunflz64dma2lizm.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: da2-jntwjassfzcwbd2ave47jjss4m

GraphQL transformer version: 2
```
### AWS への反映
```bash:コマンド
amplify push

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify push
⠧ Fetching updates to backend environment: dev from the cloud.⠋ Building resource api/reactamplified
⚠️  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

⠼ Building resource api/reactamplified✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema
✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev
    
┌──────────┬────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name          │ Operation │ Provider plugin   │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Auth     │ reactamplified8f10cd21 │ Create    │ awscloudformation │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified         │ No Change │ awscloudformation │
└──────────┴────────────────────────┴───────────┴───────────────────┘
✔ Are you sure you want to continue? (Y/n) · yes

Deployment completed.
Deployed root stack reactamplified [ ======================================== ] 3/3
        amplify-reactamplified-dev-54… AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Oct 12 2024 12:52:15…     
        apireactamplified              AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Oct 12 2024 12:51:23…     
        authreactamplified8f10cd21     AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Oct 12 2024 12:51:48…     
Deployed auth reactamplified8f10cd21 [ ======================================== ] 6/6
        UserPoolClientRole             AWS::IAM::Role                 CREATE_IN_PROGRESS             Sat Oct 12 2024 12:51:16…     
        UserPool                       AWS::Cognito::UserPool         CREATE_COMPLETE                Sat Oct 12 2024 12:51:18…     
        UserPoolClient                 AWS::Cognito::UserPoolClient   CREATE_COMPLETE                Sat Oct 12 2024 12:51:20…     
        UserPoolClientWeb              AWS::Cognito::UserPoolClient   CREATE_COMPLETE                Sat Oct 12 2024 12:51:20…     
        IdentityPool                   AWS::Cognito::IdentityPool     CREATE_COMPLETE                Sat Oct 12 2024 12:51:22…     
        IdentityPoolRoleMap            AWS::Cognito::IdentityPoolRol… CREATE_COMPLETE                Sat Oct 12 2024 12:51:25…     

Deployment state saved successfully.

GraphQL transformer version: 2
```
## srcコードの変更
:::note warn
srcコードは下記、公式ドキュメントを参照
https://docs.amplify.aws/gen1/react/start/getting-started/auth/
:::
```bash:コマンド
cat << EOF > src/App.js
import { useEffect, useState } from 'react';

import { generateClient } from 'aws-amplify/api';

import { createTodo } from './graphql/mutations';
import { listTodos } from './graphql/queries';

import { withAuthenticator, Button, Heading } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

const initialState = { name: '', description: '' };
const client = generateClient();

const App = ({ signOut, user }) => {
  const [formState, setFormState] = useState(initialState);
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    fetchTodos();
  }, []);

  function setInput(key, value) {
    setFormState({ ...formState, [key]: value });
  }

  async function fetchTodos() {
    try {
      const todoData = await client.graphql({
        query: listTodos
      });
      const todos = todoData.data.listTodos.items;
      setTodos(todos);
    } catch (err) {
      console.log('error fetching todos');
    }
  }

  async function addTodo() {
    try {
      if (!formState.name || !formState.description) return;
      const todo = { ...formState };
      setTodos([...todos, todo]);
      setFormState(initialState);
      await client.graphql({
        query: createTodo,
        variables: {
          input: todo
        }
      });
    } catch (err) {
      console.log('error creating todo:', err);
    }
  }

  return (
    <div style={styles.container}>
      <Heading level={1}>Hello {user.username}</Heading>
      <Button onClick={signOut} style={styles.button}>
        Sign out
      </Button>
      <h2>Amplify Todos</h2>
      <input
        onChange={(event) => setInput('name', event.target.value)}
        style={styles.input}
        value={formState.name}
        placeholder="Name"
      />
      <input
        onChange={(event) => setInput('description', event.target.value)}
        style={styles.input}
        value={formState.description}
        placeholder="Description"
      />
      <button style={styles.button} onClick={addTodo}>
        Create Todo
      </button>
      {todos.map((todo, index) => (
        <div key={todo.id ? todo.id : index} style={styles.todo}>
          <p style={styles.todoName}>{todo.name}</p>
          <p style={styles.todoDescription}>{todo.description}</p>
        </div>
      ))}
    </div>
  );
};

const styles = {
  container: {
    width: 400,
    margin: '0 auto',
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    padding: 20
  },
  todo: { marginBottom: 15 },
  input: {
    border: 'none',
    backgroundColor: '#ddd',
    marginBottom: 10,
    padding: 8,
    fontSize: 18
  },
  todoName: { fontSize: 20, fontWeight: 'bold' },
  todoDescription: { marginBottom: 0 },
  button: {
    backgroundColor: 'black',
    color: 'white',
    outline: 'none',
    fontSize: 18,
    padding: '12px 0px'
  }
};

export default withAuthenticator(App);
EOF

```
```bash:出力
admin:~/environment/react-amplified (master) $ cat << EOF > src/App.js
> import { useEffect, useState } from 'react';
> 
> import { generateClient } from 'aws-amplify/api';
> 
> import { createTodo } from './graphql/mutations';
> import { listTodos } from './graphql/queries';
> 
> import { withAuthenticator, Button, Heading } from '@aws-amplify/ui-react';
> import '@aws-amplify/ui-react/styles.css';
> 
> const initialState = { name: '', description: '' };
> const client = generateClient();
> 
> const App = ({ signOut, user }) => {
>   const [formState, setFormState] = useState(initialState);
>   const [todos, setTodos] = useState([]);
> 
>   useEffect(() => {
>     fetchTodos();
>   }, []);
> 
>   function setInput(key, value) {
>     setFormState({ ...formState, [key]: value });
>   }
> 
>   async function fetchTodos() {
>     try {
>       const todoData = await client.graphql({
>         query: listTodos
>       });
>       const todos = todoData.data.listTodos.items;
>       setTodos(todos);
>     } catch (err) {
>       console.log('error fetching todos');
>     }
>   }
> 
>   async function addTodo() {
>     try {
>       if (!formState.name || !formState.description) return;
>       const todo = { ...formState };
>       setTodos([...todos, todo]);
>       setFormState(initialState);
>       await client.graphql({
>         query: createTodo,
>         variables: {
>           input: todo
>         }
>       });
>     } catch (err) {
>       console.log('error creating todo:', err);
>     }
>   }
> 
>   return (
>     <div style={styles.container}>
>       <Heading level={1}>Hello {user.username}</Heading>
>       <Button onClick={signOut} style={styles.button}>
>         Sign out
>       </Button>
>       <h2>Amplify Todos</h2>
>       <input
>         onChange={(event) => setInput('name', event.target.value)}
>         style={styles.input}
>         value={formState.name}
>         placeholder="Name"
>       />
>       <input
>         onChange={(event) => setInput('description', event.target.value)}
>         style={styles.input}
>         value={formState.description}
>         placeholder="Description"
>       />
>       <button style={styles.button} onClick={addTodo}>
>         Create Todo
>       </button>
>       {todos.map((todo, index) => (
>         <div key={todo.id ? todo.id : index} style={styles.todo}>
>           <p style={styles.todoName}>{todo.name}</p>
>           <p style={styles.todoDescription}>{todo.description}</p>
>         </div>
>       ))}
>     </div>
>   );
> };
> 
> const styles = {
>   container: {
>     width: 400,
>     margin: '0 auto',
>     display: 'flex',
>     flexDirection: 'column',
>     justifyContent: 'center',
>     padding: 20
>   },
>   todo: { marginBottom: 15 },
>   input: {
>     border: 'none',
>     backgroundColor: '#ddd',
>     marginBottom: 10,
>     padding: 8,
>     fontSize: 18
>   },
>   todoName: { fontSize: 20, fontWeight: 'bold' },
>   todoDescription: { marginBottom: 0 },
>   button: {
>     backgroundColor: 'black',
>     color: 'white',
>     outline: 'none',
>     fontSize: 18,
>     padding: '12px 0px'
>   }
> };
> 
> export default withAuthenticator(App);
> EOF
```
## 動作確認
```bash:コマンド
npm start

```
```bash:出力
Compiled successfully!

You can now view react-amplified in the browser.

  Local:            http://localhost:8080
  On Your Network:  http://172.31.6.39:8080

Note that the development build is not optimized.
To create a production build, use npm run build.

webpack compiled successfully
```
Preview > Preview Running Applicationから表示確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/bd28d2fc-9227-7c87-7948-99d50459fcea.png)
![image_!.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/eb661007-fb33-951f-5dcc-7b7a5d9a00ee.png)
![image_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/a2bb6cbb-745c-52aa-ac0d-54ebc84537c7.png)
![image_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/dfae5baf-12ba-947d-47af-58c232666121.png)
# 06 AWS Amplify のハンズオン（Hosting 編）
https://docs.amplify.aws/gen1/react/start/getting-started/hosting/
## アプリケーションのホスティング
```bash:コマンド
amplify add hosting

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify add hosting
✔ Select the plugin module to execute · Hosting with Amplify Console (Managed hosting with custom domains, Continuous deployment)
? Choose a type Manual deployment

You can now publish your app using the following command:

Command: amplify publish
```
## クラウドリソースの変更とホスティングするアプリのビルド、デプロイ
### 現状のAmplify上リソースの状態確認
```bash:コマンド
amplify status

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify status

    Current Environment: dev
    
┌──────────┬────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name          │ Operation │ Provider plugin   │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Hosting  │ amplifyhosting         │ Create    │ awscloudformation │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified         │ No Change │ awscloudformation │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Auth     │ reactamplified8f10cd21 │ No Change │ awscloudformation │
└──────────┴────────────────────────┴───────────┴───────────────────┘

GraphQL endpoint: https://5dn6xw5cfreunflz64dma2lizm.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: da2-jntwjassfzcwbd2ave47jjss4m

GraphQL transformer version: 2

No amplify console domain detected
```
### アプリを公開する
```bash:コマンド
amplify publish

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify publish
⠇ Fetching updates to backend environment: dev from the cloud.⠋ Building resource api/reactamplified
⚠️  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

⠇ Building resource api/reactamplified✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified/amplify/backend/api/reactamplified/schema
✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev
    
┌──────────┬────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name          │ Operation │ Provider plugin   │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Hosting  │ amplifyhosting         │ Create    │ awscloudformation │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified         │ No Change │ awscloudformation │
├──────────┼────────────────────────┼───────────┼───────────────────┤
│ Auth     │ reactamplified8f10cd21 │ No Change │ awscloudformation │
└──────────┴────────────────────────┴───────────┴───────────────────┘
✔ Are you sure you want to continue? (Y/n) · yes

Deployment completed.
Deploying root stack reactamplified [ ==============================---------- ] 3/4
        amplify-reactamplified-dev-54… AWS::CloudFormation::Stack     UPDATE_COMPLETE_CLEANUP_IN_PR… Sat Oct 12 2024 12:59:23…     
        hostingamplifyhosting          AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Oct 12 2024 12:59:21…     
        apireactamplified              AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Oct 12 2024 12:59:20…     
        authreactamplified8f10cd21     AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Oct 12 2024 12:59:12…     
Deployed hosting amplifyhosting [ ======================================== ] 1/1
        AmplifyBranch                  AWS::Amplify::Branch           CREATE_COMPLETE                Sat Oct 12 2024 12:59:14…     

Deployment state saved successfully.

GraphQL transformer version: 2

Publish started for amplifyhosting

> react-amplified@0.1.0 build
> react-scripts build

Creating an optimized production build...
One of your dependencies, babel-preset-react-app, is importing the
"@babel/plugin-proposal-private-property-in-object" package without
declaring it in its dependencies. This is currently working because
"@babel/plugin-proposal-private-property-in-object" is already in your
node_modules folder for unrelated reasons, but it may break at any time.

babel-preset-react-app is part of the create-react-app project, which
is not maintianed anymore. It is thus unlikely that this bug will
ever be fixed. Add "@babel/plugin-proposal-private-property-in-object" to
your devDependencies to work around this error. This will make this message
go away.
  
Compiled successfully.

File sizes after gzip:

  193.07 kB  build/static/js/main.640d1653.js
  30.12 kB   build/static/css/main.a38340b4.css
  1.78 kB    build/static/js/453.75d5ea3a.chunk.js

The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

  npm install -g serve
  serve -s build

Find out more about deployment here:

  https://cra.link/deployment

✔ Zipping artifacts completed.
✔ Deployment complete!
https://dev.d14fd37vg009fk.amplifyapp.com
```
## 動作確認
ブラウザから上記URLにアクセス
![image0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/c489681b-69a2-e342-0cba-124a2fb58d4f.png)

![image_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3297641/c8284828-1026-7629-f47e-61d16d5427b8.png)

# 07 本シリーズのまとめ、リソースの削除
## Amplify (Cloud9で実施)
```bash:コマンド
amplify delete

```
```bash:出力
admin:~/environment/react-amplified (master) $ amplify delete
✔ Are you sure you want to continue? This CANNOT be undone. (This will delete all the environments of the project from the cloud and wipe out all the local files created by Amplify CLI) (y/N) · yes
⠋ Deleting resources from the cloud. This will take a few minutes.
Deleting env: dev.
✔ Project deleted in the cloud.
✅ Project deleted locally.
```
## Cloud9削除 (CloudShellで実施)
```bash:コマンド
# Cloud9削除
aws cloud9 delete-environment \
    --environment-id ${CLOUD9_ENVIRONMENT_ID}

```
```bash:出力
[cloudshell-user@ip-10-132-68-36 ~]$ # Cloud9削除
[cloudshell-user@ip-10-132-68-36 ~]$ aws cloud9 delete-environment \
>     --environment-id ${CLOUD9_ENVIRONMENT_ID}
```
## IAMユーザーの削除
```bash:コマンド
# ユーザーにアタッチされているポリシーをリスト
POLICIES=$(
    aws iam list-attached-user-policies \
        --user-name ${USER_NAME} \
        --query 'AttachedPolicies[*].PolicyArn' \
        --output text
) \
&& echo ${POLICIES}

# リスト内のポリシーをデタッチする
for POLICY in ${POLICIES}; do
    aws iam detach-user-policy \
        --user-name ${USER_NAME} \
        --policy-arn ${POLICY}
done

# アクセスキーIDの確認
IAM_ACCESSKEY_ID=$(
    aws iam list-access-keys \
        --user-name ${USER_NAME} \
        --query 'AccessKeyMetadata[*].AccessKeyId' \
        --output text
) \
&& echo ${IAM_ACCESSKEY_ID}

# アクセスキーの削除
aws iam delete-access-key \
    --user-name ${USER_NAME}\
    --access-key-id ${IAM_ACCESSKEY_ID}

# ユーザーの削除
aws iam delete-user --user-name ${USER_NAME}

```
```bash:出力
[cloudshell-user@ip-10-132-68-36 ~]$ # ユーザーにアタッチされているポリシーをリスト
[cloudshell-user@ip-10-132-68-36 ~]$ POLICIES=$(
>     aws iam list-attached-user-policies \
>         --user-name ${USER_NAME} \
>         --query 'AttachedPolicies[*].PolicyArn' \
>         --output text
> ) \
> && echo ${POLICIES}
arn:aws:iam::aws:policy/AdministratorAccess-Amplify
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # リスト内のポリシーをデタッチする
[cloudshell-user@ip-10-132-68-36 ~]$ for POLICY in ${POLICIES}; do
>     aws iam detach-user-policy \
>         --user-name ${USER_NAME} \
>         --policy-arn ${POLICY}
> done
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # アクセスキーIDの確認
[cloudshell-user@ip-10-132-68-36 ~]$ IAM_ACCESSKEY_ID=$(
>     aws iam list-access-keys \
>         --user-name ${USER_NAME} \
>         --query 'AccessKeyMetadata[*].AccessKeyId' \
>         --output text
> ) \
> && echo ${IAM_ACCESSKEY_ID}
AKIAWFKRCMKOVMB6JSX5
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # アクセスキーの削除
[cloudshell-user@ip-10-132-68-36 ~]$ aws iam delete-access-key \
>     --user-name ${USER_NAME}\
>     --access-key-id ${IAM_ACCESSKEY_ID}
[cloudshell-user@ip-10-132-68-36 ~]$ 
[cloudshell-user@ip-10-132-68-36 ~]$ # ユーザーの削除
[cloudshell-user@ip-10-132-68-36 ~]$ aws iam delete-user --user-name ${USER_NAME}
```