かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

AWS Amplify GraphQL API で TypeScript の型が生成されないにハマる

上記の AWS Amplify のチュートリアルで Background に GraphQL を追加するステップで TypeScript の型が生成されなかったりと色々とハマったのでメモ

アプリが TypeScript かどうかは自動で判断してくれる訳ではない

チュートリアルに従って amplify add api で Background に GraphQL の API を追加、amplify/backend/api/<myapi>/schema.graphqlスキーマを追加し amplify push --y でデプロイをしました。
デプロイが完了するとアプリで使えるファイルが生成されますが、これはアプリが TypeScript かどうかは無関係に JavaScript で生成されます。またデフォルトで /src/graphql に出力されるので何処に出力するかを選ぶことができませんでした。

デフォルトで amplify push --y 直後の構成

/root
  |- /amplify
  |- /myapp
  |    |- /src
  |- /src
       |- /graphql
           |- mutations.js
           |- queries.js
           |- subscriptions.js

今回はアプリを /myapp ディレクトリ内に置いていたので、/myapp/src 内に .ts ファイルで出力させたい…

.graphqlconfig.yml でコードの出力を設定できる

When you deploy your GraphQL API to the cloud, you are prompted to configure codegen. When a project is configured to generate code with codegen, it stores all the configuration .graphqlconfig.yml file in the root folder of your project. To make changes to the configuration, use amplify configure codegen.
cf. https://docs.amplify.aws/cli/graphql/client-code-generation/

amplify configure codegen コマンドを対話式で .graphqlconfig.yml ができるようです!

$ amplify configure codegen
? Choose the code generation language target
 typescript
# どこにアプリで使える GraphQL のファイルを出力するか
? Enter the file name pattern of graphql queries, mutations and subscriptions
 myapp/src/graphql/**/*.ts
? 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
# TypeScript で使える GraphQL の型のファイル名と場所を指定
? Enter the file name for the generated code
 myapp/src/API.ts
? Do you want to generate code for your newly created GraphQL API
 Yes

target を TypeScript にしてパスを指定する質問で自分のアプリに合わせて出力したいパスを指定すればOK
質問が完了すると .graphqlconfig.yml がプロジェクトのルートに生成される

.graphqlconfig.yml

projects:
  amplifyhandson:
    schemaPath: amplify/backend/api/<MyAppName>/build/schema.graphql
    includes:
      - myapp/src/graphql/**/*.ts
    excludes:
      - ./amplify/**
    extensions:
      amplify:
        codeGenTarget: typescript
        generatedFileName: myapp/src/API.ts
        docsFilePath: myapp/src/graphql
        region: ap-northeast-1
        apiId: null
        maxDepth: 2

ファイル生成するかの質問に Yes と回答しているとこの時点で GraphQL 関連のファイルが生成されている。
Schema を変更した後など改めて生成する場合は下記コマンドを実行すればOK

$ amplify codegen
✔ Generated GraphQL operations successfully and saved at myapp/src/graphql
✔ Code generated successfully and saved in file myapp/src/API.ts

👇 生成後

/root
  |- /amplify
  |- /myapp
  |    |- /src
  |        |- API.ts
  |        |- /graphql
  |            |- mutations.js
  |            |- queries.js
  |            |- subscriptions.js
  |- .graphqlconfig.yml

これで適時 API.ts などから型ファイルをインポートすればエディタ上で型の保管などが効くようになる!

.js ファイルをそのままにしているとハマりがち

特殊ケースだと思いますが今回私は、対話式で設定ファイルが作成できることを知らなかったので初回に生成された .js ファイルを手動で myapp/src/graphql 内に移動させていて、その後設定ファイルで TypeScript にできることを知り改めてファイル生成を行ったので下記のように同名の .js.ts ファイルが同階層に存在する状態になっていました。

/root
  |- /amplify
  |- /myapp
  |    |- /src
  |        |- API.ts
  |        |- /graphql
  |            |- mutations.js
  |            |- mutations.ts
  |            |- queries.js
  |            |- queries.ts
  |            |- subscriptions.js
  |            |- subscriptions.ts
  |- .graphqlconfig.yml

この状態で import { listNotes } from './graphql/queries'; のようにクエリをインポートしていたのですが、schema を変更しても一向に変更が反映されず数時間溶かしてしまいました。

原因としては単純で .graphqlconfig.yml に TypeScript の設定を追加した後は amplify codegen で出力されるのは .ts のファイルだけで、.js のファイルは古い状態のままになっていて、アプリでインポートされているのが .js ファイルだったというオチでした。

無駄にハマりを避けるために .graphqlconfig.yml を変更した後は先に生成されていたファイルは一度全て消してしまうのが良さそうです。( import されているのが .js の方だと気づくまでマジで数時間とかした… )

所感

教訓。
設定を変更したら、生成されているファイルは削除しておこう

チュートリアルの箇所に TypeScript の場合のリンク貼っておいて欲しいデス… お願いします AWS 様〜 (ᐡ o̴̶̷̤ ﻌ o̴̶̷̤ ᐡ)


[参考]