[忘備録]Amplify Gen2 Workshopの詰まり所

どうも駆け出し12冠エンジニアのアスカです。今回はAmplify Gen2のWorkshopを行ったので、その所感を記しておきます。
以下4カ所で詰まり、結果的に最後まで出来ていないです。
1. Cloud9の作成に失敗する
1. サンドボックス環境が作成出来ない...
1. products: a.hasMany('Product')の引数は二つだと怒られる...
1. graphql作成コマンドがエラーで止まる。

別のドキュメント見ながら理解を深めていきたいと思います。
この記事が同じく詰まる人の助けになれば幸いです。

# そもそもAmplifyとは...
こんな事が出来るAWSのサービスです。
- AWSのクラウドサービス上にモバイルアプリケーションを構築するための最も速く、簡単な方法。
- 利用者はクラウドサービスのバックエンドの構築をツールに任せ、アプリケーション実装に集中できる。
- ポピュラーなバックエンドの構成とそれを利用するためのフロントエンドの統合を自動で構築できる。
参考: https://qiita.com/laha/items/1e0805edacce111e9332

## Amplify Gen2とは...
バックエンドリソースのデプロイ方法が、従来の CLI から CDK に変更されたそうです。CDKと統合される事によって拡張性が高まったと思われます。
参考: https://zenn.dev/ototrip/articles/tech-nextjs-amplify-1

# 早速ワークショップをやってみる
https://catalog.workshops.aws/amplify-core/ja-JP
以下のようなアプリを約90分で作成するそうです。
![image](https://static.us-east-1.prod.workshops.aws/public/eb8d03c5-a7a9-4498-af76-e2c43066e45b/static/images/introduction/application-screenshot.png )

さっそくやってみました。
## 詰まった所①:Cloud9の作成に失敗する
ワークショップを始める前の環境作成の部分になります。基本のCloudFormationのファイルセットをダウンロードして実行する時、Cloud9の作成に失敗しました。

```

# zipファイルをダウンロード

curl 'https://static.us-east-1.prod.workshops.aws/public/eb8d03c5-a7a9-4498-af76-e2c43066e45b/assets/code/retailstore.zip' -o retailstore.zip

# CloudFormation テンプレートのダウンロード

curl 'https://static.us-east-1.prod.workshops.aws/public/eb8d03c5-a7a9-4498-af76-e2c43066e45b/static/cfn/cloud9.yaml' -o cloud9.yaml
curl 'https://static.us-east-1.prod.workshops.aws/public/eb8d03c5-a7a9-4498-af76-e2c43066e45b/static/cfn/codecommit.yaml' -o codecommit.yaml

# ブートストラップスクリプトのダウンロード

curl 'https://static.us-east-1.prod.workshops.aws/public/eb8d03c5-a7a9-4498-af76-e2c43066e45b/static/scripts/own_account.sh' -o own_account.sh

sh own_account.sh
```
(画像)

どうやらデフォルトのVPCが無い事で怒られています。
今の環境はControl Towerで作成したのでデフォルトのVPCが削除されてControl Towerでアカウント作成時に同時に作成されたVPCがある状態です。
これを指定してあげればCloud9も作成出来るのではないかと思います。

cloud9.ymlの中に以下のようにSubnetを追加するコードを追加します。(CloudShellはvimに対応)
```diff_ruby: cloud9.yml
(前略)
################## INSTANCE #####################
  Cloud9InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: '/'
      Roles:
        - Ref: Cloud9Role

  Cloud9Instance:
    DependsOn: Cloud9BootstrapAssociation
    Type: AWS::Cloud9::EnvironmentEC2
    Properties:
      Description: !Sub AWS Cloud9 instance for ${EnvironmentName}
      Repositories:
        - RepositoryUrl: !ImportValue "RepoCloneUrlHttp"
          PathComponent: RetailStore
      AutomaticStopTimeMinutes: !Ref AutomaticStopTimeMinutes
      InstanceType: !Ref InstanceType
      Name: !Ref InstanceName
      ImageId: !Ref InstanceImageId
+     SubnetId: <subnet idを指定>
      OwnerArn: 
        Fn::If:
          - AssignCloud9Owner
          - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:assumed-role/${InstanceOwner}
          - Ref: AWS::NoValue
      Tags:
        - Key: SSMBootstrap
          Value: Active
        - Key: SSMInstallFiles
          Value: Active
        - Key: Environment
          Value: !Ref EnvironmentName
(後略)
```
これでCloud9が作成されました。

## 詰まった所②: サンドボックス環境が作成出来ない...
ワークショップ上では以下のコマンドを実行するとサンドボックス環境が出来上がるとの事でした。
```
npx amplify sandbox
```
しかし、下記エラーが発生して詰まってしまいました。
```
  Amplify Sandbox

  Identifier:   ubuntu
  Stack:        amplify-retailstore-ubuntu-sandbox-7479b72030

  To specify a different sandbox identifier, use --identifier
Segmentation fault (core dumped)
```
調べてみるとNode.jsのバージョンを20から18に変更すると回避できるようです。
https://zenn.dev/p0n/articles/7cfe53ccaacdda

```
nvm install 18 # v18.19.0が入った
nvm use 18
rm -rf node_modules # v20でnpm installした場合
rm package-lock.json # v20でnpm installした場合
npm install
```
最新のバージョンとは不整合が起きるようですね。改善を待ちましょう。

## 詰まった所③:products: a.hasMany('Product')の引数は二つだと怒られる...
さすがにこんな初歩的なミスがWorkshopにある訳ないやろと思いながらも、ドキュメントを見た所、間違えていました。
参考:https://docs.amplify.aws/gen2/build-a-backend/data/data-modeling/relationships/#pageMain
このドキュメントに基づくと、カテゴリと商品の関係性を定義するには以下の変更が必要です。

```diff_typescript
const retailStoreSchema = a.schema({
  Product: a.model({
    id: a.id().required(),
    name: a.string().required(),
    description: a.string(),
    price: a.float(),
    current_stock: a.integer(),
    image: a.string(),
    rating: a.float(),
    style: a.string(),
+   category: a.belongsTo('Category', 'id'), 
  }).authorization([a.allow.public()]),
  Category: a.model({
    id: a.id().required(),
    name: a.string().required(),
    description: a.string(),
    image: a.string(),
    styles: a.string().array(),
-   products: a.hasMany('Product'),
+   products: a.hasMany('Product','id'),
  }).authorization([a.allow.public()])
});
```
この変更で無事sandboxにデプロイ出来ました。

## 詰まった所④:graphql作成コマンドがエラーで止まる。
```
npx @aws-amplify/backend-cli generate forms --stack $STACK_NAME --models Category
```
を実行すると
```
file:///home/ubuntu/environment/RetailStore/node_modules/@aws-amplify/backend-cli/lib/amplify.js:7
await parser.parseAsync(hideBin(process.argv));
^^^^^

SyntaxError: Unexpected reserved word
    at Loader.moduleStrategy (internal/modules/esm/translators.js:133:18)
    at async link (internal/modules/esm/module_job.js:42:21)
```
が表示され、graphqlが作成されないです。このエラーの原因が調べても
分からない...