

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# を使用した GraphQL APIsの設計 AWS AppSync
<a name="designing-a-graphql-api"></a>

AWS AppSync では、コンソールエクスペリエンスを使用して GraphQL APIsを作成できます。「[サンプルスキーマの起動](https://docs.aws.amazon.com/appsync/latest/devguide/quickstart.html)」セクションでこれを垣間見ました。ただし、このガイドでは、活用できるオプションと設定のカタログ全体は表示されていません AWS AppSync。

コンソールで GraphQL API を作成することを選択した場合、検討すべきオプションがいくつかあります。「[サンプルスキーマの起動](https://docs.aws.amazon.com/appsync/latest/devguide/quickstart.html)」ガイドを読んだ方には、定義済みのモデルから API を作成する方法を紹介しました。以下のセクションでは、 AWS AppSyncで GraphQL API を作成するためのその他のオプションと構成について説明します。

このセクションでは、以下を行います。

1. [Blank APIs or imports](blank-import-api.md#aws-appsync-blank-import-api): このガイドでは、GraphQL API を作成するための作成プロセス全体を説明します。モデルのない空白のテンプレートから GraphQL を作成する方法、スキーマのデータソースを設定する方法、最初のリゾルバーをフィールドに追加する方法を学習します。

1. [Real-time data](aws-appsync-real-time-data.md#aws-appsync-real-time-data-anchor): このガイドでは、 の WebSocket エンジンを使用して API AWS AppSyncを作成するための潜在的なオプションを示します。

1. [Merged APIs](merged-api.md#aws-appsync-merged-api): このガイドでは、複数の既存の GraphQL API のデータを関連付けてマージすることにより、新しい GraphQL API を作成する方法を説明します。

1. [RDS イントロスペクションを使用した GraphQL API の構築](rds-introspection.md): このガイドでは、Data API を使用して Amazon RDS テーブルを統合する方法を説明します。

# GraphQL API の構築 (空の API またはインポートされた API)
<a name="blank-import-api"></a>

空白のテンプレートから GraphQL API を作成する前に、GraphQL に関する概念を確認しておくと役に立ちます。GraphQL API には次の 3 つの基本的なコンポーネントがあります。

1. **スキーマ**は、データの形状と定義が含まれているファイルです。GraphQL サービスに対してクライアントによってリクエストが実行されるとき、返されるデータはスキーマの仕様に従います。詳細については、「[GraphQL スキーマ](schema-components.md#aws-appsync-schema-components)」を参照してください。

1. **データソース**はスキーマにアタッチされます。リクエストが実行されると、ここでデータが取得され、変更されます。詳細については、「[ データソース](data-source-components.md#aws-appsync-data-source-components)」を参照してください。

1. **リゾルバー**はスキーマとデータソースの間に存在します。リクエストが実行されると、リゾルバーはソースからデータに対してオペレーションを実行し、結果をレスポンスとして返します。詳細については、「[ リゾルバー](resolver-components.md#aws-appsync-resolver-components)」を参照してください。

![\[GraphQL API architecture showing schema, resolvers, and data sources connected via AppSync.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/appsync-architecture-graphql-api.png)


AWS AppSync は、スキーマとリゾルバーのコードを作成、編集、保存できるようにすることで APIs を管理します。データソースは、データベース、DynamoDB テーブル、Lambda 関数などの外部リポジトリから取得されます。 AWS サービスを使用してデータを保存する場合、またはデータを保存することを計画している場合、 は AWS アカウントから GraphQL APIs にデータを関連付けたときに、ほぼシームレスなエクスペリエンス AWS AppSync を提供します。

次のセクションでは、 AWS AppSync サービスを使用してこれらの各コンポーネントを作成する方法について説明します。

**Topics**
+ [GraphQL スキーマの設計](designing-your-schema.md)
+ [データソースを追加する](attaching-a-data-source.md)
+ [AWS AppSync リゾルバーの設定](resolver-config-overview.md)
+ [CDK での API の使用](using-your-api.md)

# GraphQL スキーマの設計
<a name="designing-your-schema"></a>

GraphQL スキーマは、あらゆる GraphQL サーバー実装の基盤です。各 GraphQL API は、リクエストからのデータがどのように入力されるかを記述するタイプとフィールドを含む**単一の**スキーマによって定義されます。API を経由するデータフローと実行される操作は、スキーマと照合して検証する必要があります。

[GraphQL タイプシステム](https://graphql.org/learn/schema/#type-system)は、GraphQL サーバーの機能を記述し、クエリが有効であることを判別するために使用されます。サーバーのタイプシステムはしばしばそのサーバーのスキーマと呼ばれ、さまざまなオブジェクトタイプ、スカラー型、入力型などで構成されます。GraphQL は宣言型であると同時に厳密に型付けされています。つまり、型はランタイムに明確に定義され、指定されたものだけを返します。

AWS AppSync では、GraphQL スキーマを定義および設定できます。次のセクションでは、 AWS AppSyncのサービスを使用して GraphQL スキーマを最初から作成する方法について説明します。

## GraphQL スキーマの構造化
<a name="schema-structure"></a>

**ヒント**  
続ける前に「[スキーマ](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)」セクションを確認することをおすすめします。

GraphQL は API サービスを実装するための強力なツールです。[GraphQL のウェブサイト](https://graphql.org/)によると、GraphQL は以下の通りです。

「*GraphQL は API 用のクエリ言語であり、既存のデータでそれらのクエリを実行するためのランタイムです。GraphQL は、API 内のデータを完全かつわかりやすく説明し、クライアントが必要としているものだけを尋ねることができるようにし、時間の経過とともに API を進化させやすくし、強力な開発者ツールを可能にします*」

このセクションでは、GraphQL 実装の最初の部分であるスキーマについて説明します。上の引用を使用すると、スキーマは「API 内のデータを完全かつわかりやすく説明する」役割を果たします。言い換えると、GraphQL スキーマは、サービスのデータ、操作、およびそれらの間の関係をテキストで表現したものです。スキーマは、GraphQL サービス実装の主要なエントリポイントと見なされます。当然のことながら、多くの場合、プロジェクトで最初に作成するものの 1 つです。次に進む前に「[スキーマ](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)」セクションを確認することをおすすめします。

「[スキーマ](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)」セクションを引用すると、GraphQL スキーマは*スキーマ定義言語* (SDL) で記述されています。SDL は、構造が確立された型とフィールドで構成されています。
+ **タイプ**: タイプとは、GraphQL がデータの形状と動作を定義する方法です。GraphQL は、このセクションの後半で説明する多数の型をサポートしています。スキーマで定義されている各タイプには、独自のスコープが含まれます。スコープ内には、GraphQL サービスで使用される値またはロジックを含むことができる 1 つ以上のフィールドがあります。型にはさまざまな役割がありますが、最も一般的なのはオブジェクトまたはスカラー (プリミティブ値型) です。
+ **フィールド**: フィールドはタイプのスコープ内に存在し、GraphQL サービスから要求された値を保持します。これらは他のプログラミング言語の変数とよく似ています。フィールドで定義するデータの形状によって、リクエスト/レスポンス操作におけるデータの構造が決まります。これにより、開発者はサービスのバックエンドがどのように実装されているかを知らなくても、何が返されるかを予測できます。

最も単純なスキーマには、次の 3 つの異なるデータカテゴリが含まれます。

1. **スキーマルート**: ルートはスキーマのエントリポイントを定義します。データの追加、削除、変更などの操作を行うフィールドを指します。

1. **タイプ**: これらはデータの形状を表すために使用される基本タイプです。これらは概して、定義された特性を持つ何かのオブジェクト、または抽象的な表現と考えることができます。例えば、データベース内の人を表す `Person` オブジェクトを作成できます。各個人の特性はフィールド `Person` として内部で定義されます。名前、年齢、職業、住所など何でも構いません。

1. **特殊オブジェクトタイプ**: スキーマ内の操作の動作を定義するタイプです。特殊オブジェクトタイプはそれぞれ、スキーマごとに 1 回定義されます。これらは最初にスキーマのルートに配置され、次にスキーマ本体で定義されます。特別なオブジェクトタイプの各フィールドは、リゾルバーによって実装される単一の操作を定義します。

これを大局的に見ると、著者とその著者が書いた本を保存するサービスを作成していると想像してみてください。各著者には名前と執筆した本の配列があります。各本には名前と関連する著者のリストがあります。また、本や著者を追加したり、検索したりできる機能も必要です。この関係を単純な UML 表現で表現すると、次のようになります。

![\[UML diagram showing Author and Book classes with attributes and methods, linked by association.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/GraphQL-UML-1.png)


GraphQL では、`Author` および `Book` エンティティとはスキーマ内の 2 つの異なるオブジェクトタイプを表します。

```
type Author {
}

type Book {
}
```

`Author` には `authorName` と `Books` が含まれ、`Book` には `bookName` と`Authors` が含まれます。これらはタイプのスコープ内のフィールドとして表すことができます。

```
type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}
```

ご覧のとおり、型表現は図と非常に似ています。しかし、メソッドは少し難しいところです。これらは、いくつかの特殊なオブジェクトタイプのいずれかにフィールドとして配置されます。特殊なオブジェクト分類は、その動作によって異なります。GraphQL には、クエリ、ミューテーション、およびサブスクリプションの 3 つの基本的な特殊オブジェクトタイプがあります。[特別なオブジェクト](https://docs.aws.amazon.com//appsync/latest/devguide/graphql-types.html#special-object-components)の詳細については、 を参照してください。

`getAuthor`と`getBook`はどちらもデータを要求しているため、`Query` の特別なオブジェクトタイプに配置されます。

```
type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}
```

オペレーションはクエリにリンクされ、クエリ自体もスキーマにリンクされます。スキーマルートを追加すると、特別なオブジェクトタイプ (この場合は `Query`) がエントリポイントの 1 つとして定義されます。これは `schema` キーワードを使用して行うことがＤけいます。

```
schema {
  query: Query
}

type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}
```

最後の 2 つの方法を見てみると、`addAuthor` と `addBook` はデータベースにデータを追加しているので、これらは`Mutation` の特別なオブジェクトタイプで定義されます。ただし、[タイプ](https://docs.aws.amazon.com/appsync/latest/devguide/graphql-types.html#input-components)ページを見ると、オブジェクトを直接参照する入力は厳密には出力タイプなので、許可されていないこともわかります。この場合、`Author` または `Book` は使用できないため、同じフィールドを持つ入力タイプを作成する必要があります。この例では、`AuthorInput` と `BookInput` を追加しましたが、どちらもそれぞれのタイプの同じフィールドを受け入れます。次に、入力をパラメータとして使用してミューテーションを作成します。

```
schema {
  query: Query
  mutation: Mutation
}

type Author {
  authorName: String
  Books: [Book]
}

input AuthorInput {
  authorName: String
  Books: [BookInput]
}

type Book {
  bookName: String
  Authors: [Author]
}

input BookInput {
  bookName: String
  Authors: [AuthorInput]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}

type Mutation {
  addAuthor(input: [BookInput]): Author
  addBook(input: [AuthorInput]): Book
}
```

先ほど行ったことを振り返ってみましょう。

1. エンティティを表すための `Book` および `Author` タイプを含むスキーマを作成しました。

1. エンティティの特徴を含むフィールドを追加しました。

1. この情報をデータベースから取得するクエリを追加しました。

1. データベース内のデータを操作するミューテーションを追加しました。

1. GraphQL のルールに準拠するため、ミューテーション内のオブジェクトパラメータを置き換える入力タイプを追加しました。

1. GraphQL 実装がルートタイプの場所を理解できるように、クエリとミューテーションをルートスキーマに追加しました。

ご覧のとおり、スキーマを作成するプロセスには、一般的なデータモデリング (特にデータベースモデリング) から多くの概念が取り入れられています。スキーマはソースからのデータの形に合っていると考えることができます。リゾルバーが実装するモデルとしても機能します。以下のセクションでは、さまざまな AWSバックアップツールとサービスを使用してスキーマを作成する方法について説明します。

**注記**  
以下のセクションの例は、実際のアプリケーションで実行するためのものではありません。これらの説明は、ユーザーが独自のアプリケーションを構築できるようにコマンドを紹介することのみを目的としています。

## スキーマの作成
<a name="creating-schema"></a>

スキーマは というファイルにあります`schema.graphql`。 AWS AppSync を使用すると、ユーザーはさまざまな方法を使用して GraphQL APIs の新しいスキーマを作成できます。この例では、空の API と空白のスキーマを作成します。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **ダッシュボード**で、**[API の作成]** を選択します。

   1. **[API オプション]** で、**[GraphQL API]**、**[最初から設計]**、**[次へ]** の順に選択します。

      1. **API 名**では、あらかじめ入力されている名前をアプリケーションに必要な名前に変更します。

      1. **連絡先情報**については、API のマネージャーを特定する連絡先を入力できます。これはオプションのフィールドです。

      1. **[Private API 設定]** で、プライベート API 機能を有効にできます。プライベート API には、設定された VPC エンドポイント (VPCE) からのみアクセスできます。詳細については、「[プライベート DNS](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html)」を参照してください。

         この例では、この機能を有効にすることはお勧めしません。**[次へ]** 選択して入力を確認します。

   1. **[GraphQL タイプを作成]** では、データソースとして使用する DynamoDB テーブルを作成するか、この作業をスキップして後で作成するかを選択できます。

      この例では、**[GraphQL リソースを後で作成]** を選択します。リソースは別のセクションで作成します。

   1. 入力内容を確認し、**[API を作成]** を選択します。

1. 特定の API のダッシュボードが表示されます。API の名前がダッシュボードの上部にあるのでわかります。そうでない場合は、**サイドバー**で **[API]** を選択し、**API ダッシュボード**で API を選択できます。

   1. API 名の下の**サイドバー**で、**[スキーマ]** を選択します。

1. **スキーマエディタでは**、ファイルを設定できます。`schema.graphql`ファイルは空でも、モデルから生成されたタイプで埋め込まれていてもかまいません。右側には、リゾルバーをスキーマフィールドにアタッチするための **[リゾルバー]** セクションがあります。このセクションではリゾルバーについては説明しません。

------
#### [ CLI ]

**注記**  
CLI を使用するときは、サービス内のリソースにアクセスして作成するための正しい権限を持っていることを確認してください。サービスにアクセスする必要がある管理者以外のユーザーには、[最小特権](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)ポリシーを設定するとよいでしょう。 AWS AppSync ポリシーの詳細については、「 の [Identity and Access Management AWS AppSync](https://docs.aws.amazon.com//appsync/latest/devguide/security-iam.html)」を参照してください。  
まだの場合は、コンソール版最初に読むことをお勧めします。

1. まだをインストールしてしていない場合は、 AWS CLI を[インストール](https://docs.aws.amazon.com//cli/latest/userguide/cli-chap-getting-started.html)して設定します。

1. [https://docs.aws.amazon.com/cli/latest/reference/appsync/create-graphql-api.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-graphql-api.html)コマンドを実行して GraphQL API オブジェクトを作成します。

   この特定のコマンドには、次の 2 つのパラメータを入力する必要があります。

   1. API の `name` です。

   1. `authentication-type`、または API へのアクセスに使用される認証情報の種類 (IAM、OIDC など)。
**注記**  
`Region` など、その他のパラメータは設定する必要がありますが、通常はデフォルトで CLI 設定値になります。

   コマンドの例は、次のようになります。

   ```
   aws appsync create-graphql-api --name testAPI123 --authentication-type API_KEY
   ```

   出力は CLI に返されます。例を示します。

   ```
   {
       "graphqlApi": {
           "xrayEnabled": false,
           "name": "testAPI123",
           "authenticationType": "API_KEY",
           "tags": {},
           "apiId": "abcdefghijklmnopqrstuvwxyz",
           "uris": {
               "GRAPHQL": "https://zyxwvutsrqponmlkjihgfedcba.appsync-api.us-west-2.amazonaws.com/graphql",
               "REALTIME": "wss://zyxwvutsrqponmlkjihgfedcba.appsync-realtime-api.us-west-2.amazonaws.com/graphql"
           },
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz"
       }
   }
   ```

1. 
**注記**  
これはオプションコマンドで、既存のスキーマを取得し、base-64 BLOB を使用して AWS AppSync サービスにアップロードします。この例では、このコマンドは使用しません。

   [https://docs.aws.amazon.com/cli/latest/reference/appsync/start-schema-creation.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/start-schema-creation.html) コマンドを実行します。

   この特定のコマンドには、次の 2 つのパラメータを入力する必要があります。

   1. `api-id` は前のステップからのものです。

   1. スキーマ `definition`は base-64 でエンコードされたバイナリブロブです。

   コマンドの例は、次のようになります。

   ```
    aws appsync start-schema-creation --api-id abcdefghijklmnopqrstuvwxyz --definition "aa1111aa-123b-2bb2-c321-12hgg76cc33v"
   ```

   次のような出力が返されます。

   ```
   {
       "status": "PROCESSING"
   }
   ```

   このコマンドは処理後の最終出力を返しません。結果を確認するには別のコマンド [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/get-schema-creation-status.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/get-schema-creation-status.html) を使用する必要があります。この 2 つのコマンドは非同期なので、スキーマの作成中でも出力ステータスを確認できることに注意してください。

------
#### [ CDK ]

**ヒント**  
CDK を使用する前に、CDK の[公式ドキュメント](https://docs.aws.amazon.com/cdk/v2/guide/home.html)と CDK AWS AppSyncリファレンスを確認することをお勧めします。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
以下の手順では、特定のリソースを追加するために使用するスニペットの一般的な例のみを示しています。これは本番稼働用コードで機能するソリューションとなることを**意図したものではありません**。また、動作するアプリが既にあることを前提としています。

1. CDK の開始点は少し異なります。理想的には、`schema.graphql` ファイルはすでに作成されているはずです。必要なのは、`.graphql` ファイル拡張子が付いた新しいファイルを作成することだけです。空のリストを指定できます。

1. 一般的には、使用しているサービスにインポートディレクティブを追加しなければならない場合があります。たとえば、次の形式に従います。

   ```
   import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
   import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
   ```

   GraphQL API を追加するには、スタックファイルで AWS AppSync サービスをインポートする必要があります。

   ```
   import * as appsync from 'aws-cdk-lib/aws-appsync';
   ```
**注記**  
つまり、`appsync` キーワードでサービス全体をインポートすることになります。アプリでこれを使用するには、 AWS AppSync コンストラクトは の形式を使用します`appsync.construct_name`。例えば、GraphQL API を作りたいなら、`new appsync.GraphqlApi(args_go_here)` と言うでしょう。次のステップはこれを描写しています。

1. 最も基本的な GraphQL API には、API 用の `name` と `schema` パスが含まれます。

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     name: 'name_of_API_in_console',
     schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema_name.graphql')),
   });
   ```
**注記**  
このスニペットが何をするのか見てみましょう。`api` の範囲内では、`appsync.GraphqlApi(scope: Construct, id: string, props: GraphqlApiProps)` を呼び出して新しい GraphQL API を作成しています。スコープは `this` で、現在のオブジェクトを参照します。ID は *API\$1ID* で、作成 CloudFormation 時に の GraphQL API のリソース名になります。`GraphqlApiProps` には、GraphQL API の `name` と `schema` が含まれています。`schema` は、`.graphql` ファイル (*schema\$1name.graphql*) の絶対パス (`__dirname`) を検索してスキーマ (`SchemaFile.fromAsset`) を生成します。実際のシナリオでは、スキーマファイルはおそらく CDK アプリ内にあるでしょう。  
GraphQL API に加えた変更を使用するには、アプリを再デプロイする必要があります。

------

## スキーマへのタイプの追加
<a name="adding-schema-types"></a>

スキーマを追加したので、入力タイプと出力タイプの両方を追加し始めることができます。ここで説明する型は実際のコードでは使用しないでください。これらはプロセスの理解に役立つ例に過ぎません。

まず、オブジェクトタイプを作成します。実際のコードでは、これらのタイプから始める必要はありません。GraphQL の規則と構文に従っていれば、いつでも好きなタイプを作ることができます。

**注記**  
次のいくつかのセクションでは**スキーマエディター**を使用するので、これを開いたままにしておきます。

------
#### [ Console ]
+ オブジェクトタイプは、`type` キーワードとタイプ名を使用して作成できます。

  ```
  type Type_Name_Goes_Here {}
  ```

  タイプのスコープ内には、オブジェクトの特性を表すフィールドを追加できます。

  ```
  type Type_Name_Goes_Here {
    # Add fields here
  }
  ```

  例を示します。

  ```
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  ```
**注記**  
このステップでは、必須の `id` フィールドを `ID` として格納し、`title` フィールドを `String` として格納し、`date` フィールドを `AWSDateTime` として格納する汎用オブジェクトタイプを追加しました。タイプとフィールド、およびその機能の一覧については、「[スキーマ](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)」を参照してください。スカラーの一覧とその機能については、[タイプのリファレンス](https://docs.aws.amazon.com/appsync/latest/devguide/type-reference.html)を参照してください。

------
#### [ CLI ]

**注記**  
まだの場合は、コンソール版最初に読むことをお勧めします。
+ オブジェクトタイプは [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html) コマンドを実行して作成できます。

  この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

  1. API の `api-id` です。

  1. `definition`、またはタイプのコンテンツです。コンソールの例では、次のようになっていました。

     ```
     type Obj_Type_1 {
       id: ID!
       title: String
       date: AWSDateTime
     }
     ```

  1. 入力の `format` です。この例では、`SDL` を使用します。

  コマンドの例は、次のようになります。

  ```
  aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Obj_Type_1{id: ID! title: String date: AWSDateTime}" --format SDL
  ```

  出力は CLI に返されます。例を示します。

  ```
  {
      "type": {
          "definition": "type Obj_Type_1{id: ID! title: String date: AWSDateTime}",
          "name": "Obj_Type_1",
          "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Obj_Type_1",
          "format": "SDL"
      }
  }
  ```
**注記**  
このステップでは、必須の `id` フィールドを `ID` として格納し、`title` フィールドを `String` として格納し、`date` フィールドを `AWSDateTime` として格納する汎用オブジェクトタイプを追加しました。タイプとフィールド、およびその機能の一覧については、「[スキーマ](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)」を参照してください。スカラーの一覧とその機能については、[タイプのリファレンス](https://docs.aws.amazon.com/appsync/latest/devguide/type-reference.html)を参照してください。  
さらにお気づきかもしれませんが、定義を直接入力しても、小さいタイプでは有効ですが、大きい型や複数のタイプを追加することはできません。`.graphql` ファイルにすべてを追加し、[それを入力として渡す](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters-file.html)こともできます。

------
#### [ CDK ]

**ヒント**  
CDK を使用する前に、CDK の[公式ドキュメント](https://docs.aws.amazon.com/cdk/v2/guide/home.html)と CDK AWS AppSyncリファレンスを確認することをお勧めします。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
以下の手順では、特定のリソースを追加するために使用するスニペットの一般的な例のみを示しています。これは本番稼働用コードで機能するソリューションとなることを**意図したものではありません**。また、動作するアプリが既にあることを前提としています。

タイプを追加するには、`.graphql` ファイルに追加する必要があります。例えば、コンソールの例は次のとおりです。

```
type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}
```

他のファイルと同様に、タイプをスキーマに直接追加できます。

**注記**  
GraphQL API に加えた変更を使用するには、アプリを再デプロイする必要があります。

------

[オブジェクトタイプ](https://graphql.org/learn/schema/#object-types-and-fields)には、文字列や整数などの[スカラー型](https://graphql.org/learn/schema/#scalar-types)であるフィールドがあります。 AWS AppSync では、基本 GraphQL スカラー`AWSDateTime`に加えて、 などの拡張スカラー型を使用することもできます。また、名前が感嘆符で終わっているフィールドは必須フィールドです。

`ID` スカラー型は、`String` または `Int` のいずれかである一意の識別子です。これらはリゾルバーのマッピングテンプレートで自動割り当てを制御できます。

`Query` のような特別なオブジェクトタイプと上記の例のような「通常の」オブジェクトタイプでは、どちらも`type` キーワードを使用し、オブジェクトと見なされるという点で類似点があります。ただし、特殊オブジェクトタイプ (`Query`、`Mutation`、および`Subscription`) は API のエントリポイントとして公開されるため、動作が大きく異なります。また、データというよりは、オペレーションのシェーピングに関するものでもあります。詳細については、「[The Query and Mutation types](https://graphql.org/learn/schema/#the-query-and-mutation-types)」を参照してください。

特殊なオブジェクトタイプについて言えば、次のステップは、1 つまたは複数のオブジェクトタイプを追加して、シェーピングされたデータに対して操作を実行することです。実際のシナリオでは、すべての GraphQL スキーマには、データをリクエストするためのルートクエリタイプが少なくとも必要です。クエリは、GraphQL サーバーのエントリポイント (またはエンドポイント) の 1 つと考えることができます。例としてクエリを追加してみましょう。

------
#### [ Console ]
+ クエリを作成するには、他のタイプと同様にスキーマファイルに追加するだけです。クエリには、次のような `Query` タイプとルート内のエントリが必要です。

  ```
  schema {
    query: Name_of_Query
  }
  
  type Name_of_Query {
    # Add field operation here
  }
  ```

  プロダクション環境の *Name\$1of\$1Query* は、ほとんどの場合、単純に `Query` と呼ばれることに注意してください。この値のままにしておくことをお勧めします。クエリタイプ内にはフィールドを追加できます。各フィールドはリクエスト内でオペレーションを実行します。その結果、すべてではないにしても、ほとんどのフィールドがリゾルバーにアタッチされます。ただし、このセクションではその点については触れません。フィールドのオペレーションの形式については、次のようになります。

  ```
  Name_of_Query(params): Return_Type # version with params
  Name_of_Query: Return_Type # version without params
  ```

  例を示します。

  ```
  schema {
    query: Query
  }
  
  type Query {
    getObj: [Obj_Type_1]
  }
  
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  ```
**注記**  
このステップでは、`Query` タイプを追加して `schema` ルートで定義しました。`Query` タイプは、`Obj_Type_1` オブジェクトのリストを返す `getObj` フィールドを定義しました。`Obj_Type_1` が前のステップのオブジェクトであることに注意してください。プロダクションコードでは、フィールド操作は通常、`Obj_Type_1` のようなオブジェクトによって形成されたデータを処理します。さらに、`getObj` のようなフィールドには通常、ビジネスロジックを実行するリゾルバーがあります。これについては別のセクションで説明します。  
追加の注意点として、 はエクスポート中にスキーマルート AWS AppSync を自動的に追加するため、技術的にはスキーマに直接追加する必要はありません。弊社のサービスは重複するスキーマを自動的に処理します。ベストプラクティスとしてここに追加しています。

------
#### [ CLI ]

**注記**  
まだの場合は、コンソール版最初に読むことをお勧めします。

1. [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html) コマンドを実行して `query` 定義付きの `schema` ルートを作成します。

   この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

   1. API の `api-id` です。

   1. `definition`、またはタイプのコンテンツです。コンソールの例では、次のようになっていました。

      ```
      schema {
        query: Query
      }
      ```

   1. 入力の `format` です。この例では、`SDL` を使用します。

   コマンドの例は、次のようになります。

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "schema {query: Query}" --format SDL
   ```

   出力は CLI に返されます。例を示します。

   ```
   {
       "type": {
           "definition": "schema {query: Query}",
           "name": "schema",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```
**注記**  
`create-type` コマンドに正しく入力しなかった場合は、[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html) コマンドを実行することでスキーマルート (またはスキーマ内の任意のタイプ) を更新できることに注意してください。この例では、`subscription` 定義を含むようにスキーマルートを一時的に変更します。  
この特定のコマンドでは、いくつかのパラメータを入力する必要があります。  
API の `api-id` です。
タイプの `type-name`。コンソールの例では、これは `schema` でした。
`definition`、またはタイプのコンテンツです。コンソールの例では、次のようになっていました。  

      ```
      schema {
        query: Query
      }
      ```
`subscription` を追加した後のスキーマは次のようになります。  

      ```
      schema {
        query: Query
        subscription: Subscription
      }
      ```
入力の `format` です。この例では、`SDL` を使用します。
コマンドの例は、次のようになります。  

   ```
   aws appsync update-type --api-id abcdefghijklmnopqrstuvwxyz --type-name schema --definition "schema {query: Query subscription: Subscription}" --format SDL
   ```
出力は CLI に返されます。例を示します。  

   ```
   {
       "type": {
           "definition": "schema {query: Query subscription: Subscription}",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```
この例でも、フォーマット済みのファイルを追加しても問題ありません。

1. [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html) コマンドを実行して `Query` タイプを作成します。

   この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

   1. API の `api-id` です。

   1. `definition`、またはタイプのコンテンツです。コンソールの例では、次のようになっていました。

      ```
      type Query {
        getObj: [Obj_Type_1]
      }
      ```

   1. 入力の `format` です。この例では、`SDL` を使用します。

   コマンドの例は、次のようになります。

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Query {getObj: [Obj_Type_1]}" --format SDL
   ```

   出力は CLI に返されます。例を示します。

   ```
   {
       "type": {
           "definition": "Query {getObj: [Obj_Type_1]}",
           "name": "Query",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Query",
           "format": "SDL"
       }
   }
   ```
**注記**  
このステップでは、`Query` タイプを追加して `schema` ルートで定義しました。`Query` タイプは、`Obj_Type_1` オブジェクトのリストを返す `getObj` フィールドを定義しました。  
`schema` ルートコードでは`query: Query`、`query:` 部分はクエリがスキーマで定義されたことを示し、`Query` 部分は実際の特別なオブジェクト名を示します。

------
#### [ CDK ]

**ヒント**  
CDK を使用する前に、CDK の[公式ドキュメント](https://docs.aws.amazon.com/cdk/v2/guide/home.html)と CDK AWS AppSyncリファレンスを確認することをお勧めします。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
以下の手順では、特定のリソースを追加するために使用するスニペットの一般的な例のみを示しています。これは本番稼働用コードで機能するソリューションとなることを**意図したものではありません**。また、動作するアプリが既にあることを前提としています。

クエリとスキーマルートを `.graphql` ファイルに追加する必要があります。この例は以下の例のようになっていますが、実際のスキーマコードに置き換える必要があります。

```
schema {
  query: Query
}

type Query {
  getObj: [Obj_Type_1]
}

type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}
```

他のファイルと同様に、タイプをスキーマに直接追加できます。

**注記**  
スキーマルートの更新は任意です。ベストプラクティスとして、この例に追加しました。  
GraphQL API に加えた変更を使用するには、アプリを再デプロイする必要があります。

------

オブジェクトと特殊オブジェクト (クエリ) の両方を作成する例を見てきました。また、これらを相互に接続してデータや操作を記述する方法についても説明しました。データ記述と 1 つ以上のクエリのみを含むスキーマを作成できます。ただし、データソースにデータを追加する操作をもう 1 つ追加したいと考えています。データを変更する `Mutation` と呼ばれる特別なオブジェクトタイプを追加します。

------
#### [ Console ]
+ ミューテーションは`Mutation`と呼ばれます。`Query` と同様に、`Mutation` 内部のフィールド操作は操作を記述し、リゾルバーにアタッチされます。また、これは特殊なオブジェクトタイプなので、`schema` ルートで定義する必要があることにも注意してください。ミューテーションの例を示します。

  ```
  schema {
    mutation: Name_of_Mutation
  }
  
  type Name_of_Mutation {
    # Add field operation here
  }
  ```

  一般的なミューテーションは、クエリのようにルートにリストされます。ミューテーションは `type` キーワードと名前を使って定義されます。通常は *Name\$1of\$1Mutation* が`Mutation`と呼ばれるので、そのままにしておくことをおすすめします。各フィールドはオペレーションも実行します。フィールドのオペレーションの形式については、次のようになります。

  ```
  Name_of_Mutation(params): Return_Type # version with params
  Name_of_Mutation: Return_Type # version without params
  ```

  例を示します。

  ```
  schema {
    query: Query
    mutation: Mutation
  }
  
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  
  type Query {
    getObj: [Obj_Type_1]
  }
  
  type Mutation {
    addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
  }
  ```
**注記**  
このステップでは、`addObj` フィールドのある `Mutation` タイプを追加しました。このフィールドの機能をまとめてみましょう。  

  ```
  addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
  ```
`addObj` では `Obj_Type_1` オブジェクトを使用してオペレーションを実行しています。これはフィールドがあるから明らかですが、構文では `: Obj_Type_1` 戻り値のタイプでもそれが証明されています。`addObj` 内部では、`Obj_Type_1` オブジェクトの`id`、`title`、`date` フィールドをパラメータとして受け付けています。ご覧のとおり、これはメソッド宣言によく似ています。ただし、メソッドの動作についてはまだ説明していません。前述のように、スキーマはデータとオペレーションの内容を定義するためだけのもので、オペレーションの方法を定義するものではありません。実際のビジネスロジックの実装は、後で最初のリゾルバーを作成するときに実装します。  
スキーマが完成したら、それを `schema.graphql` ファイルとしてエクスポートするオプションがあります。**スキーマエディター**で **[スキーマをエクスポート]** を選択すると、サポートされている形式でファイルをダウンロードできます。  
追加の注意点として、 はエクスポート中にスキーマルート AWS AppSync を自動的に追加するため、技術的にはスキーマに直接追加する必要はありません。弊社のサービスは重複するスキーマを自動的に処理します。ベストプラクティスとしてここに追加しています。

------
#### [ CLI ]

**注記**  
まだの場合は、コンソール版最初に読むことをお勧めします。

1. [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html) コマンドを実行してルートスキーマを更新します。

   この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

   1. API の `api-id` です。

   1. タイプの `type-name`。コンソールの例では、これは `schema` でした。

   1. `definition`、またはタイプのコンテンツです。コンソールの例では、次のようになっていました。

      ```
      schema {
        query: Query
        mutation: Mutation
      }
      ```

   1. 入力の `format` です。この例では、`SDL` を使用します。

   コマンドの例は、次のようになります。

   ```
   aws appsync update-type --api-id abcdefghijklmnopqrstuvwxyz --type-name schema --definition "schema {query: Query mutation: Mutation}" --format SDL
   ```

   出力は CLI に返されます。例を示します。

   ```
   {
       "type": {
           "definition": "schema {query: Query mutation: Mutation}",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```

1. [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html) コマンドを実行して `Mutation` タイプを作成します。

   この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

   1. API の `api-id` です。

   1. `definition`、またはタイプのコンテンツです。コンソールの例では、次のようになっていました。

      ```
      type Mutation {
        addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
      }
      ```

   1. 入力の `format` です。この例では、`SDL` を使用します。

   コマンドの例は、次のようになります。

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Mutation {addObj(id: ID! title: String date: AWSDateTime): Obj_Type_1}" --format SDL
   ```

   出力は CLI に返されます。例を示します。

   ```
   {
       "type": {
           "definition": "type Mutation {addObj(id: ID! title: String date: AWSDateTime): Obj_Type_1}",
           "name": "Mutation",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation",
           "format": "SDL"
       }
   }
   ```

------
#### [ CDK ]

**ヒント**  
CDK を使用する前に、CDK の[公式ドキュメント](https://docs.aws.amazon.com/cdk/v2/guide/home.html)と CDK AWS AppSyncリファレンスを確認することをお勧めします。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
以下の手順では、特定のリソースを追加するために使用するスニペットの一般的な例のみを示しています。これは本番稼働用コードで機能するソリューションとなることを**意図したものではありません**。また、動作するアプリが既にあることを前提としています。

クエリとスキーマルートを `.graphql` ファイルに追加する必要があります。この例は以下の例のようになっていますが、実際のスキーマコードに置き換える必要があります。

```
schema {
  query: Query
  mutation: Mutation
}

type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}

type Query {
  getObj: [Obj_Type_1]
}

type Mutation {
  addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
}
```

**注記**  
スキーマルートの更新は任意です。ベストプラクティスとして、この例に追加しました。  
GraphQL API に加えた変更を使用するには、アプリを再デプロイする必要があります。

------

## その他の考慮事項 - 列挙型をステータスとして使用する
<a name="optional-consideration-enums"></a>

これで、基本的なスキーマの作り方がわかりました。しかし、スキーマの機能を高めるために追加できることはたくさんあります。アプリケーションによく見られることの 1 つは、列挙型をステータスとして使用することです。列挙型を使用すると、呼び出し時に値のセットから特定の値を強制的に選択させることができます。これは、長期間にわたって大幅に変化することはないとわかっている場合に便利です。仮説的に言えば、レスポンスにステータスコードまたは文字列を返す列挙型を追加できるかもしれません。

例として、ユーザーの投稿データをバックエンドに保存するソーシャルメディアアプリを作っているとしましょう。このスキーマには、個々の投稿のデータを表す `Post` タイプが含まれています。

```
type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}
```

私たちの `Post` には一意の `id`、投稿 `title`、投稿の `date` と、アプリによって処理された投稿の状態を表す `PostStatus` と呼ばれるという列挙型が含まれます。今回の操作では、すべての投稿データを返すクエリを用意します。

```
type Query {
  getPosts: [Post]
}
```

また、データソースに投稿を追加するミューテーションもあります。

```
type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}
```

スキーマを見ると、`PostStatus` 列挙型には複数のステータスがある可能性があります。`success` (投稿は正常に処理されました)、`pending` (投稿は処理中)、`error` (投稿は処理できません) という 3 つの基本的な状態が必要な場合があります。列挙型を追加するには、次のようにします。

```
enum PostStatus {
  success
  pending
  error
}
```

完全なスキーマは次のようになります。

```
schema {
  query: Query
  mutation: Mutation
}

type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}

type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}

type Query {
  getPosts: [Post]
}

enum PostStatus {  
  success
  pending
  error
}
```

ユーザーがアプリケーションに `Post` を追加すると、そのデータを処理する `addPost` オペレーションが呼び出されます。`addPost` にアタッチされたリゾルバーがデータを処理している間、`poststatus` はオペレーションの状態で継続的に更新されます。クエリを実行すると、`Post` にはデータの最終ステータスが含まれます。データをスキーマ内でどのように動作させたいかを説明しているだけだということを覚えておいてください。ここではリゾルバーの実装について多くのことを想定しています。リゾルバーは、リクエストを満たすためにデータを処理するための実際のビジネスロジックを実装します。

## オプションとしての考慮事項 - サブスクリプション
<a name="optional-consideration-subscriptions"></a>

 AWS AppSync のサブスクリプションは、ミューテーションへの応答として呼び出されます。サブスクリプションは、`Subscription` 型と `@aws_subscribe()` ディレクティブを使用してスキーマで設定して、どのミューテーションが 1 つまたは複数のサブスクリプションを呼び出すかを示します。サブスクリプションの設定については、「[リアルタイムデータ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html)」を参照してください。

## オプションとしての考慮事項 - リレーションとページ分割
<a name="optional-consideration-relations-and-pagination"></a>

DynamoDB テーブルに 100 万個の `Posts` が格納されていて、そのデータの一部を返したいとします。ただし、上記のクエリ例では、すべての投稿を返すだけです。リクエストするたびにこれらすべてを取得したいとは思わないでしょう。代わりに、それらを[ページ分割](https://graphql.org/learn/pagination/)したいと思うかもしれません。スキーマを次のように変更します。
+ `getPosts` フィールドに、`nextToken` (イテレーター) と `limit` (イテレーション制限) の 2 つの入力引数を追加します。
+ `Posts` (`Post` オブジェクトのリストを取得) と `nextToken` (イテレーター) `PostIterator` フィールドを含む新しい タイプを追加します。
+ `getPosts` を変更すると、`Post` オブジェクトのリストではなく、`PostIterator` を返します。

```
schema {
  query: Query
  mutation: Mutation
}

type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}

type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}

type Query {
  getPosts(limit: Int, nextToken: String): PostIterator
}

enum PostStatus {
  success
  pending
  error
}

type PostIterator {
  posts: [Post]
  nextToken: String
}
```

`PostIterator` タイプにより、`Post` オブジェクトのリストと、次ののバッチを取得するための `nextToken` を返すことができます。`PostIterator` 内部には、ページ分割トークン (`nextToken`) とともに返される `Post` アイテム (`[Post]`) のリストがあります。 AWS AppSync では、これはリゾルバーを介して Amazon DynamoDB に接続され、暗号化されたトークンとして自動的に生成されます。マッピングテンプレートにより、`limit` 引数の値は `maxResults` パラメータに変換され、`nextToken` 引数の値は `exclusiveStartKey` パラメータに変換されます。 AWS AppSync コンソールでの例および組み込みテンプレートサンプルについては、「[リゾルバーのリファレンス (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html)」を参照してください。

# AWS AppSync でのデータソースのアタッチ
<a name="attaching-a-data-source"></a>

データソースは、GraphQL APIsできる AWS アカウントのリソースです。 AWS AppSync は、Amazon DynamoDB AWS Lambda、リレーショナルデータベース (Amazon Aurora Serverless)、Amazon OpenSearch Service、HTTP エンドポイントなどの多数のデータソースをサポートしています。 AWS AppSync API は、複数のデータソースとやり取りするように設定できるため、データを 1 つの場所に集約できます。 AWS AppSync は、アカウントから既存の AWS リソースを使用するか、スキーマ定義からユーザーに代わって DynamoDB テーブルをプロビジョニングできます。

次のセクションでは、GraphQL API にデータソースをアタッチする方法について説明します。

## データソースのタイプ
<a name="data-source-types"></a>

 AWS AppSync コンソールでスキーマを作成したら、それにデータソースをアタッチできます。API を初めて作成する場合、定義済みスキーマの作成中に Amazon DynamoDB テーブルをプロビジョニングするオプションがあります。ただし、このセクションではそのオプションについては説明しません。この例については、「[Launching a schema](https://docs.aws.amazon.com//appsync/latest/devguide/schema-launch-start.html)」セクションを参照してください。

代わりに、 AWS AppSync がサポートするすべてのデータソースを確認します。アプリケーションに適したソリューションを選ぶ要因は多数あります。以下のセクションでは、各データソースの追加のコンテキストについて説明します。データソースに関する一般的な情報については、「[データソース](https://docs.aws.amazon.com/appsync/latest/devguide/data-source-components.html)」を参照してください。

### Amazon DynamoDB
<a name="data-source-type-ddb"></a>

Amazon DynamoDB は、スケーラブルなアプリケーション向けの主要なストレージソリューションの 1 AWSつです。DynamoDB のコアコンポーネントは **テーブル**で、これは単なるデータのコレクションです。通常テーブルは、`Book` や `Author` などのエンティティに基づいて作成されます。テーブルエントリの情報は、各エントリに固有のフィールドのグループである**アイテム**として保存されます。アイテム全体は、データベース内の 1 つの行またはレコードを表します。たとえば、`Book` エントリのアイテムにはその値とともに `title` と `author` が含まれる場合があります。`title` や `author` などの個々のフィールドは**属性**と呼ばれ、リレーショナルデータベースの列の値に似ています。

ご想像のとおり、テーブルはアプリケーションからのデータの保存に使用されます。 AWS AppSync を使用すると、DynamoDB テーブルを GraphQL API に接続してデータを操作できます。**フロントエンドのウェブとモバイルのブログからこの[ユースケース](https://aws.amazon.com/blogs/mobile/new-real-time-multi-group-app-with-aws-amplify-graphql-build-a-twitter-community-clone/)を見てみましょう。このアプリケーションでは、ユーザーがソーシャルメディアアプリにサインアップできます。ユーザーはグループに参加して投稿をアップロードできます。この投稿は、そのグループに登録している他のユーザーにブロードキャストされます。ユーザーのアプリケーションは、ユーザー、投稿、ユーザーグループの情報を DynamoDB に保存します。GraphQL API ( によって管理 AWS AppSync) は DynamoDB テーブルとインターフェイスします。フロントエンドに反映される変更をユーザーがシステムで行うと、GraphQL API はその変更を取得し、リアルタイムで他のユーザーにブロードキャストします。

### AWS Lambda
<a name="data-source-type-lam"></a>

Lambda は、イベントへの応答としてコードを実行するために必要なリソースを自動的に構築するイベント駆動型サービスです。Lambda は、リソースを実行するためのコード、依存関係、設定を含むグループステートメントである**関数**を使用します。関数は、関数を呼び出すアクティビティのグループである**トリガー**を検出すると自動的に実行されます。トリガーは、API コールを行うアプリケーション、リソースをスピンアップするアカウントの AWS サービスなどです。トリガーされると、関数は、変更するデータを含む JSON ドキュメントである**イベント**を処理します。

Lambda は、コードを実行するためのリソースをプロビジョニングしなくてもコードを実行するのに適しています。**フロントエンドのウェブとモバイルのブログからこの[ユースケース](https://aws.amazon.com/blogs/mobile/building-a-graphql-api-with-java-and-aws-lambda/)を見てみましょう。このユースケースは、DynamoDB セクションで紹介した内容と少し似ています。このアプリケーションでは、GraphQL API により投稿の追加 (ミューテーション) やそのデータの取得 (クエリ) などのオペレーションが定義されます。オペレーション (`getPost ( id: String ! ) : Post`、`getPostsByAuthor ( author: String ! ) : [ Post ]` など) の機能を実装するために、Lambda 関数が使用され、インバウンドリクエストが処理されます。*オプション 2: Lambda リゾルバー AWS AppSync では*、 AWS AppSync サービスを使用してスキーマを維持し、Lambda データソースをオペレーションの 1 つにリンクします。オペレーションが呼び出されると、Lambda は Amazon RDS Proxy とやり取りして、データベース上でビジネスロジックを実行します。

### Amazon RDS
<a name="data-source-type-RDS"></a>

Amazon RDS では、リレーショナルデータベースを迅速に構築して設定できます。Amazon RDS では、クラウド内の隔離されたデータベース環境として機能する汎用**データベースインスタンス**を作成します。このインスタンスでは、実際の RDBMS ソフトウェア (PostgreSQL、MySQL など) である **DB エンジン**を使用します。このサービスは、 AWSインフラストラクチャを使用したスケーラビリティ、パッチ適用や暗号化などのセキュリティサービスを提供し、デプロイの管理コストを削減することで、バックエンド作業の多くをオフロードします。

Lambda セクションの同じ[ユースケース](https://aws.amazon.com/blogs/mobile/building-a-graphql-api-with-java-and-aws-lambda/)を見てみましょう。*オプション 3:Amazon RDS リゾルバー AWS AppSync では*、 の GraphQL API を Amazon RDS に直接リンク AWS AppSync する別のオプションがあります。このオプションでは、[データ API](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html) を使用して、データベースが GraphQL API に関連付けられます。リゾルバーはフィールド (通常はクエリ、ミューテーション、サブスクリプション) にアタッチされ、データベースへのアクセスに必要な SQL ステートメントを実装します。クライアントによってフィールドを呼び出すリクエストが行われると、リゾルバーはステートメントを実行してレスポンスを返します。

### Amazon EventBridge
<a name="data-source-type-eventbridge"></a>

EventBridge では、アタッチするサービスまたはアプリケーション (**イベントソース**) からイベントを受信し、一連のルールに基づいて処理するパイプラインである**イベントバス**を作成します。**イベント**は実行環境における一種の状態の変化であり、**ルール**はイベントのフィルタのセットです。ルールは、**イベントパターン**、すなわちイベントの状態変化のメタデータ (ID、リージョン、アカウント番号、ARN など) に従います。イベントがイベントパターンと一致すると、EventBridge はパイプラインを介して送信先サービス (**ターゲット**) にイベントを送信し、ルールで指定されたアクションをトリガーします。

EventBridge は、状態が変化するオペレーションを他のサービスにルーティングするのに適しています。**フロントエンドのウェブとモバイルのブログからこの[ユースケース](https://aws.amazon.com/blogs/mobile/appsync-eventbridge/)を見てみましょう。この例は、異なるサービスを複数のチームで管理している e コマースソリューションを示しています。これらのサービスの 1 つは、フロントエンドの配送の各ステップ (注文済み、進行中、出荷済み、配送済みなど) で顧客に注文の更新情報を提供します。ただし、このサービスを管理するフロントエンドチームは、別のバックエンドチームによって管理されている注文システムデータに直接アクセスすることはできません。バックエンドチームの注文システムはブラックボックスとも呼ばれており、データの構造化に関する情報を収集するのは困難です。しかし、バックエンドチームは、EventBridge によって管理されるイベントバスを通じて、注文データを発行したシステムをセットアップしました。イベントバスからのデータにアクセスしてフロントエンドにルーティングするために、フロントエンドチームは GraphQL API をポイントする新しいターゲットを作成しました AWS AppSync。また、注文の更新情報に関連するデータのみを送信するルールも作成しました。更新が行われると、イベントバスからのデータが GraphQL API に送信されます。API のスキーマによってデータが処理され、フロントエンドに渡されます。

### none データソース
<a name="data-source-type-none"></a>

データソースを使用する予定がない場合は、データソースを `none` に設定します。`none` データソースは、設定後も明示的にデータソースとして分類されますが、ストレージメディアではありません。通常、リゾルバーはある時点で 1 つ以上のデータソースを呼び出してリクエストを処理します。ただし、データソースを操作する必要がない場合もあります。データソースを `none` に設定すると、リクエストが実行され、データ呼び出しステップはスキップされて、レスポンスが実行されます。

EventBridge セクションの同じ[ユースケース](https://aws.amazon.com/blogs/mobile/appsync-eventbridge/)を見てみましょう。スキーマでは、ミューテーションによりステータスの更新が処理されて、サブスクライバーに送信されます。リゾルバーの仕組み上、通常は少なくとも 1 つのデータソース呼び出しがあります。ただし、このシナリオのデータは既にイベントバスによって自動的に送信されています。つまり、ミューテーションによりデータソース呼び出しが実行される必要はなく、注文状況はローカルで処理するだけで済みます。ミューテーションは `none` に設定され、パススルー値として機能し、データソースは呼び出されません。その後、スキーマにデータが入力され、サブスクライバーに送信されます。

### OpenSearch
<a name="data-source-type-opensearch"></a>

Amazon OpenSearch Service は、全文検索、データ視覚化、ロギングを実装するためのツールスイートです。このサービスを使用すると、アップロードした構造化データをクエリできます。

このサービスでは、OpenSearch のインスタンスを作成します。これらは**ノード**と呼ばれます。ノードには、少なくとも 1 つの**インデックス**を追加します。概念的には、インデックスはリレーショナルデータベースのテーブルに少し似ています (ただし、OpenSearch は ACID に準拠していないため、同じようには使用できません)。OpenSearch サービスにアップロードするデータをインデックスに入力します。データがアップロードされると、インデックス内に存在する 1 つ以上のシャードにインデックスが作成されます。**シャード**は、データの一部を含むインデックスのパーティションのようなもので、他のシャードと別にクエリできます。アップロードされたデータは、**ドキュメント**と呼ばれる JSON ファイルとして構造化されます。その後、ノードに対してドキュメント内のデータをクエリできます。

### HTTP エンドポイント
<a name="data-source-type-http"></a>

HTTP エンドポイントをデータソースとして使用できます。 AWS AppSync は、パラメータやペイロードなどの関連情報を含むリクエストをエンドポイントに送信できます。HTTP レスポンスはリゾルバーに公開され、リゾルバーはオペレーション終了後に最終レスポンスを返します。

## データソースを追加する
<a name="adding-a-data-source"></a>

データソースを作成した場合は、 AWS AppSync サービス、具体的には API にリンクできます。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **ダッシュボード**で API を選択します。

   1. **サイドバー** で **[データソース]** を選択します。

1. **[データソースを作成]** を選択します。

   1. データソースに名前を付けます。説明を付けることもできますが、これは任意です。

   1. **[データソースタイプ]** を選択します。

   1. DynamoDB の場合は、リージョンを選択してから、リージョンのテーブルを選択する必要があります。新しい汎用テーブルロールを作成するか、テーブルの既存のロールをインポートするかを選択することで、テーブルとのインタラクションルールを設定できます。[バージョニング](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html)を有効にすると、複数のクライアントが同時にデータの更新を試行したとき、リクエストごとにデータのバージョンが自動的に作成されます。バージョニングは、競合の検出と解決を目的に、データの複数のバリアントを保持および管理するために使用されます。また、スキーマ自動生成を有効にすると、データソースが取得され、スキーマ内でそのデータソースにアクセスするのに必要な CRUD、`List`、`Query` オペレーションがいくつか生成されます。

      OpenSearch では、リージョンを選択してから、リージョンのドメイン (クラスター) を選択する必要があります。新しい汎用テーブルロールを作成するか、テーブルの既存のロールをインポートするかを選択することで、ドメインとのインタラクションルールを設定できます。

      Lambda の場合は、リージョンを選択してから、そのリージョンの Lambda 関数の ARN を選択する必要があります。新しい汎用テーブルロールを作成するか、テーブルの既存のロールをインポートするかを選択することで、Lambda 関数とのインタラクションルールを設定できます。

      HTTP の場合は、HTTP エンドポイントを入力する必要があります。

      EventBridge の場合は、リージョンを選択してから、地域のイベントバスを選択する必要があります。新しい汎用テーブルロールを作成するか、テーブルの既存のロールをインポートするかを選択することで、イベントバスとのインタラクションルールを設定できます。

      RDS の場合は、リージョンを選択してから、次にシークレットストア (ユーザー名とパスワード)、データベース名、スキーマを選択する必要があります。

      None の場合は、実際のデータソースがないデータソースを追加します。これは、リゾルバーを実際のデータソースではなくローカルで処理するためのものです。
**注記**  
既存のロールをインポートする場合は、信頼ポリシーが必要です。信頼ポリシーの詳細については、「[IAM 信頼ポリシー](#iam-trust-policy.title)」を参照してください。

1. **[作成]** を選択します。
**注記**  
または、DynamoDB データソースを作成する場合は、コンソールの **[スキーマ]** ページに移動し、ページ上部の **[リソースの作成]** を選択してから、定義済みのモデルを入力してテーブルに変換することもできます。このオプションでは、基本型を入力またはインポートし、パーティションキーを含む基本的なテーブルデータを設定して、スキーマの変更を確認します。

------
#### [ CLI ]
+ [https://docs.aws.amazon.com/cli/latest/reference/appsync/create-data-source.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-data-source.html) コマンドを実行してデータソースを作成します。

  この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

  1. API の `api-id` です。

  1. テーブルの `name`。

  1. データソースの `type`。選択したデータソースタイプに応じて、`service-role-arn` と `-config` タグの入力が必要になる場合があります。

  コマンドの例は、次のようになります。

  ```
   aws appsync create-data-source --api-id abcdefghijklmnopqrstuvwxyz --name data_source_name --type data_source_type --service-role-arn arn:aws:iam::107289374856:role/role_name --[data_source_type]-config {params}
  ```

------
#### [ CDK ]

**ヒント**  
CDK を使用する前に、CDK の[公式ドキュメント](https://docs.aws.amazon.com/cdk/v2/guide/home.html)と CDK AWS AppSyncリファレンスを確認することをお勧めします。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
以下の手順では、特定のリソースを追加するために使用するスニペットの一般的な例のみを示しています。これは本番稼働用コードで機能するソリューションとなることを**意図したものではありません**。また、動作するアプリが既にあることを前提としています。

特定のデータソースを追加するには、コンストラクトをスタックファイルに追加する必要があります。データソースタイプのリストは次のとおりです。
+  [ DynamoDbDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.DynamoDbDataSource.html) 
+  [ EventBridgeDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.EventBridgeDataSource.html) 
+  [ HttpDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.HttpDataSource.html) 
+  [ LambdaDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.LambdaDataSource.html) 
+  [ NoneDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.NoneDataSource.html) 
+  [ OpenSearchDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.OpenSearchDataSource.html) 
+  [ RdsDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.RdsDataSource.html) 

1. 一般的には、使用しているサービスにインポートディレクティブを追加しなければならない場合があります。たとえば、次の形式に従います。

   ```
   import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
   import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
   ```

   たとえば、 AWS AppSync および DynamoDB サービスをインポートする方法は次のとおりです。

   ```
   import * as appsync from 'aws-cdk-lib/aws-appsync';
   import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
   ```

1. RDS などの一部のサービスでは、データソースを作成する前にスタックファイルに追加の設定が必要です (VPC の作成、ロール、アクセス認証情報など)。詳細については、関連する CDK ページの例を参照してください。

1. ほとんどのデータソース、特に AWS サービスでは、スタックファイルにデータソースの新しいインスタンスを作成します。通常、結果は以下のようになります。

   ```
   const add_data_source_func = new service_scope.resource_name(scope: Construct, id: string, props: data_source_props);
   ```

   その例として、Amazon DynamoDB テーブルの例を次に示します。

   ```
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
     partitionKey: {
       name: 'id',
       type: dynamodb.AttributeType.STRING,
     },
     sortKey: {
       name: 'id',
       type: dynamodb.AttributeType.STRING,
     },
     tableClass: dynamodb.TableClass.STANDARD,
   });
   ```
**注記**  
ほとんどのデータソースには、少なくとも 1 つの必須の props が含まれます (`?` 記号を**使用しない**で表記します)。必要とされる props については、CDK ドキュメントを参照してください。

1. 次に、データソースを GraphQL API にリンクする必要があります。おすすめの方法は、パイプラインリゾルバーの関数を作成するときに追加することです。たとえば、以下のスニペットは DynamoDB テーブルのすべての要素をスキャンする関数です。

   ```
   const add_func = new appsync.AppsyncFunction(this, 'func_ID', {
     name: 'func_name_in_console',
     add_api,
     dataSource: add_api.addDynamoDbDataSource('data_source_name_in_console', add_ddb_table),
     code: appsync.Code.fromInline(`
         export function request(ctx) {
           return { operation: 'Scan' };
         }
   
         export function response(ctx) {
           return ctx.result.items;
         }
     `),
     runtime: appsync.FunctionRuntime.JS_1_0_0,
   });
   ```

   `dataSource` props では、GraphQL API (`add_api`) を呼び出し、その組み込みメソッドの 1 つ (`addDynamoDbDataSource`) を使用して、テーブルと GraphQL API を関連付けることができます。引数は、 AWS AppSync コンソール (`data_source_name_in_console`この例では ) とテーブルメソッド () に存在するこのリンクの名前です`add_ddb_table`。このトピックの詳細は、リゾルバーの作成を開始する次のセクションで明らかになります。

   データソースをリンクする方法は他にもあります。技術的には、テーブル関数の props リストに `api` を追加することもできます。たとえば、以下はステップ 3 のスニペットですが、`api` props には GraphQL API が含まれています。

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     ...
   });
   
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
   
    ...
   
     api: add_api
   });
   ```

   または、`GraphqlApi` コンストラクトを個別に呼び出すこともできます。

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     ...
   });
   
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
     ...
   });
   
   const link_data_source = add_api.addDynamoDbDataSource('data_source_name_in_console', add_ddb_table);
   ```

   アソシエーションは関数の props でのみ作成することをおすすめします。それ以外の場合は、 AWS AppSync コンソールでリゾルバー関数をデータソースに手動でリンクするか (コンソール値 を使用し続ける場合`data_source_name_in_console`)、 のような別の名前で関数に別の関連付けを作成する必要があります`data_source_name_in_console_2`。これは、props による情報処理の方法に制限があるためです。
**注記**  
変更を確認するには、アプリを再デプロイする必要があります。

------

### IAM 信頼ポリシー
<a name="iam-trust-policy"></a>

データソースに既存の IAM ロールを使用している場合は、Amazon DynamoDB テーブルなど、 AWS リソースでオペレーションを実行するための適切なアクセス許可をそのロール`PutItem`に付与する必要があります。また、次のポリシー例に示すように、 AWS AppSync がリソースアクセスに使用するには、そのロールの信頼ポリシーを変更する必要があります。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": "appsync.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
        }
    ]
}
```

------

また、信頼ポリシーに条件を追加して、必要に応じてデータソースへのアクセスを制限することもできます。現在、`SourceArn`および`SourceAccount`キーはこれらの条件で使用できます。たとえば、次のポリシーでは、データソースへのアクセスを`123456789012` アカウントに制限しています。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        }
      }
    }
  ]
}
```

------

または、データソースへのアクセスを、次のポリシーを使用する`abcdefghijklmnopq`のような特定の API に制限することもできます。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:appsync:us-west-2:123456789012:apis/abcdefghijklmnopq"
        }
      }
    }
  ]
}
```

------

以下のポリシー`us-east-1`を使用して、 などの特定のリージョンからのすべての AWS AppSync APIs へのアクセスを制限できます。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:appsync:us-east-1:123456789012:apis/*"
        }
      }
    }
  ]
}
```

------

次のセクション (「[リゾルバーの設定](https://docs.aws.amazon.com//appsync/latest/devguide/resolver-config-overview.html)」) では、リゾルバーのビジネスロジックを追加し、スキーマのフィールドにアタッチして、データソースのデータを処理します。

詳細については、**「IAM ユーザーガイド」の「[ロールの修正](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_manage_modify.html)」を参照してください。

AppSync の AWS Lambda リゾルバーのクロスアカウントアクセスの詳細については、「[AWS AppSync のクロスアカウント AWS Lambda リゾルバーの構築](https://aws.amazon.com/blogs/mobile/appsync-lambda-cross-account/)」を参照してください。 AWS AppSync

# AWS AppSync でリゾルバーを設定する
<a name="resolver-config-overview"></a>

前のセクションでは、GraphQL スキーマとデータソースを作成し、それらを AWS AppSync サービス内でリンクする方法を学びました。スキーマでは、クエリとミューテーションに 1 つ以上のフィールド (オペレーション) を設定している場合があります。スキーマには、操作がデータソースに要求するデータの種類が記述されていましたが、それらの操作がデータに対してどのように動作するかは実装されていませんでした。

操作の動作は常にリゾルバーに実装され、リゾルバーは操作を実行するフィールドにリンクされます。リゾルバーの詳細な仕組みについては、[リゾルバー](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html)ページを参照してください。

AWS AppSync では、リゾルバーはランタイム、つまりリゾルバーが実行される環境に関連付けられています。ランタイムは、リゾルバーを記述する言語を決定します。現在、APPSYNC\$1JS (JavaScript) と Apache Velocity (VTL) の 2 つのランタイムがサポートされています。

リゾルバーを実装する場合、リゾルバーは次のような一般的な構造になっています。
+ **before Step**: クライアントからリクエストが送信されると、使用中のスキーマフィールド (通常はクエリ、ミューテーション、サブスクリプション) のリゾルバーにリクエストデータが渡されます。リゾルバーは before step ハンドラーを使用してリクエストデータの処理を開始します。これにより、データがリゾルバーを通過する前に一部の前処理操作を実行できます。
+ **関数**: before ステップが実行されると、リクエストは関数リストに渡されます。リストの最初の関数がデータソースに対して実行されます。関数は、独自のリクエストハンドラーとレスポンスハンドラーを含むリゾルバーのコードのサブセットです。リクエストハンドラーはリクエストデータを取得し、データソースに対して操作を実行します。レスポンスハンドラーは、データソースのレスポンスを処理してからリストに戻します。関数が複数ある場合、リクエストデータはリスト内の次に実行される関数に送信されます。リスト内の関数は、開発者が定義した順序で連続して実行されます。すべての関数が実行されると、最終結果は後のステップに渡されます。
+ **after step**: after step は、GraphQL レスポンスに渡す前に、最終関数のレスポンスに対していくつかの最終操作を実行できるハンドラー関数です。

このフローはパイプラインリゾルバーの例です。パイプラインリゾルバーはどちらのランタイムでもサポートされています。ただし、これはパイプラインリゾルバーで何ができるかを簡単に説明したものです。また、ここでは考えられるリゾルバー構成を 1 つだけ説明しています。サポートされているリゾルバー構成の詳細については、APPSYNC\$1JS の「[JavaScript リゾルバーの概要](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)」または VTL の「[リゾルバーマッピングテンプレートの概要](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-overview.html)」を参照してください。

ご覧のとおり、リゾルバーはモジュール式です。リゾルバーのコンポーネントが正しく動作するためには、他のコンポーネントからの実行状態を覗き見できる必要があります。[リゾルバー](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html)セクションを見れば、リゾルバーの各コンポーネントには、実行状態に関する重要な情報を一連の引数 (`args`、`context`など) として渡すことができることがわかります。AWS AppSync では、これは `context` が厳密に処理します。これは解決対象のフィールドに関する情報を格納するコンテナです。これには、渡される引数、結果、承認データ、ヘッダーデータなど、あらゆるものが含まれます。コンテキストの詳細については、APPSYNC\$1JS の「[リゾルバーコンテキストオブジェクトリファレンス](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)」または VTL の「リゾルバーマッピングテンプレートコンテキストリファレンス」を参照してください。

リゾルバーの実装に使用できるツールはコンテキストだけではありません。AWS AppSync は値の生成、エラー処理、解析、変換などのための幅広いユーティリティをサポートします。APPSYNC\$1JS の場合は[こちら](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html)、VTL の場合は[こちら](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html)でユーティリティのリストを確認できます。

以下のセクションでは、GraphQL API でリゾルバーを設定する方法を学習します。

**Topics**
+ [基本的なクエリの作成 (JavaScript)](configuring-resolvers-js.md)
+ [基本クエリの作成 (VTL)](configuring-resolvers.md)

# 基本的なクエリの作成 (JavaScript)
<a name="configuring-resolvers-js"></a>

GraphQL リゾルバーは、タイプのスキーマのフィールドをデータソースに接続します。リゾルバーはリクエストを実行するメカニズムです。

 AWS AppSync のリゾルバーは、JavaScript を使用して GraphQL 式をデータソースが使用できる形式に変換します。または、マッピングテンプレートを [Apache Velocity Template Language (VTL)](https://velocity.apache.org/engine/2.0/vtl-reference.html) で記述すると、GraphQL 表現をデータソースで使用できる形式に変換できます。

このセクションでは、JavaScript を使用してリゾルバーを設定する方法を説明します。「[リゾルバーのチュートリアル (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html)」セクションでは、JavaScript を使用してリゾルバーを実装する方法に関する詳細なチュートリアルを提供します。「[リゾルバーのリファレンス (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html)」セクションでは、JavaScript リゾルバーと共に使用できるユーティリティオペレーションについて説明します。

前述のチュートリアルを使用する前に、このガイドに従うことをお勧めします。

このセクションでは、リゾルバーを作成してクエリとミューテーションを実行するために設定する方法について説明します。

**注記**  
このガイドでは、スキーマが作成済みで、少なくとも 1 つのクエリまたはミューテーションが含まれていることを前提としています。サブスクリプション (リアルタイムデータ) をお探しの場合は、[このガイド](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html)を参照してください。

このセクションでは、リゾルバーを設定する一般的な手順と、以下のスキーマを使用する例を紹介します。

```
// schema.graphql file

input CreatePostInput {
  title: String
  date: AWSDateTime
}

type Post {
  id: ID!
  title: String
  date: AWSDateTime
}

type Mutation {
  createPost(input: CreatePostInput!): Post
}

type Query {
  getPost: [Post]
}
```

## 基本的なクエリリゾルバーの作成
<a name="create-basic-query-resolver-js"></a>

このセクションでは、基本的なクエリリゾルバーを作成する方法を説明します。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[スキーマ]** を選択します。

1. スキーマとデータソースの詳細を入力します。詳細については、「[スキーマの設計](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html)」と「[データソースを追加する](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)」の各セクションを参照してください。

1. **[スキーマ]** エディターの横に **[リゾルバー]** という名前のウィンドウがあります。このボックスには、**[スキーマ]** ウィンドウで定義されているタイプとフィールドのリストが含まれています。フィールドにはリゾルバーをアタッチできます。ほとんどの場合、フィールド処理にリゾルバーをアタッチすることになります。このセクションでは、簡単なクエリの設定について説明します。**[クエリ]** 型で、クエリのフィールドの横にある **[アタッチ]** を選択します。

1. **[リゾルバーをアタッチ]** ページの **[リゾルバータイプ]** で、パイプラインリゾルバーとユニットリゾルバーのどちらかを選択できます。これらのリゾルバータイプの詳細については、「[リゾルバー](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html)」を参照してください。このガイドでは `pipeline resolvers` を使用します。
**ヒント**  
パイプラインリゾルバーを作成すると、データソースがパイプライン関数にアタッチされます。関数は、パイプラインリゾルバー自体を作成した後に作成されます。そのため、このページにはこれを設定するオプションはありません。ユニットリゾルバーを使用する場合は、データソースがリゾルバーに直接関連付けられるため、このページで設定します。

   **[リゾルバーランタイム]** では、[`APPSYNC_JS`] を選択して JavaScript ランタイムを有効化します。

1. この API の[キャッシュ](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html)は有効にできます。現時点では、この機能をオフにすることをお勧めします。**[作成]** を選択します。

1. **[リゾルバーを編集]** ページには、リゾルバーハンドラーとレスポンス (before および after ステップ) のロジックを実装できる**リゾルバーコード**というコードエディターがあります。詳細については、「[JavaScript リゾルバーの概要](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)」を参照してください。
**注記**  
この例では、リクエストを空白のままにし、[context](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html) からの最後のデータソース結果を返すようにレスポンスを設定します。  

   ```
   import {util} from '@aws-appsync/utils';
   
   export function request(ctx) {
       return {};
   }
   
   export function response(ctx) {
       return ctx.prev.result;
   }
   ```

   このセクションの下には、**[関数]** というテーブルがあります。[関数] では、複数のリゾルバーで再利用できるコードを実装できます。コードを絶えず書き換えたりコピーしたりする代わりに、ソースコードを関数として保存し、必要なときにいつでもリゾルバーに追加できます。

   関数はパイプラインのオペレーションリストの大部分を構成します。リゾルバーで複数の関数を使用する場合、関数の順序を設定すると、関数はその順序で順番に実行されます。これらの関数は、リクエスト関数の実行後、レスポンス関数の開始前に実行されます。

   新しい関数を追加するには、**[関数]** で **[関数を追加]**、**[新しい関数の作成]** の順に選択します。代わりに **[関数の作成]** ボタンが表示されて選択できる場合もあります。

   1. データソースを選択します。これがリゾルバーの処理対象となるデータソースになります。
**注記**  
この例では、`id` で `Post` オブジェクトを取得する `getPost` にリゾルバーをアタッチします。このスキーマ用の DynamoDB テーブルをすでにセットアップ済みであると仮定します。そのパーティションキーは `id` に設定されており、空です。

   1. `Function name` を入力します。

   1. **[関数コード]** で、関数の動作を実装する必要があります。わかりにくいかもしれませんが、各関数には独自のローカルのリクエストハンドラーとレスポンスハンドラーがあります。リクエストが実行され、次にデータソース呼び出しが実行されてリクエストが処理され、データソースのレスポンスがレスポンスハンドラーによって処理されます。結果は [context](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html) オブジェクトに保存されます。その後、リスト内の次の関数が実行されるか、それが最後の関数であればステップ後のレスポンスハンドラーに渡されます。
**注記**  
この例では、データソースから `Post` オブジェクトのリストを取得する `getPost` にリゾルバーをアタッチします。リクエスト関数はテーブルにデータをリクエストし、テーブルはレスポンスをコンテキスト (ctx) に渡し、レスポンスは結果をコンテキストに返します。 AWS AppSyncの強度は、他の AWS サービスとの相互接続性にあります。DynamoDB を使用しているため、このような作業を簡略化するための[一連のオペレーション](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html)があります。他のデータソースタイプについても共通する例がいくつかあります。  
コードは以下のようになります。  

      ```
      import { util } from '@aws-appsync/utils';
      
      /**
       * Performs a scan on the dynamodb data source
       */
      export function request(ctx) {
        return { operation: 'Scan' };
      }
      
      /**
       * return a list of scanned post items
       */
      export function response(ctx) {
        return ctx.result.items;
      }
      ```
このステップでは、次の 2 つの関数を追加しました。  
`request`: リクエストハンドラーはデータソースに対して取得オペレーションを実行します。引数には、コンテキストオブジェクト (`ctx`)、または特定のオペレーションを実行するすべてのリゾルバーが利用できるデータが含まれます。たとえば、認可データや解決対象のフィールド名などが含まれる場合があります。return ステートメントは [https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan](https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan) オペレーションを実行します (例は[こちら](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html)を参照)。DynamoDB を使用しているため、そのサービスの一部のオペレーションを使用できます。このスキャンでは、テーブル内のすべての項目の基本的なフェッチが実行されます。このオペレーションの結果は、レスポンスハンドラーに渡される前に `result` コンテナーとしてコンテキストオブジェクトに保存されます。`request` はパイプライン内のレスポンス前に実行されます。
`response`: `request` の出力を返すレスポンスハンドラー。引数は、更新されたコンテキストオブジェクトで、return ステートメントは `ctx.prev.result` です。ガイドのこの段階では、この値についてはよくわからないかもしれません。`ctx` は context object オブジェクトを参照します。`prev` はパイプライン内の直前のオペレーション、この例では `request` を参照します。`result` には、リゾルバーがパイプラインを経由して移動する際の結果が含まれます。すべてをまとめると、`ctx.prev.result` は最後に実行されたオペレーションの結果であるリクエストハンドラーを返します。

   1. 完了したら、**[作成]** を選択します。

1. リゾルバー画面に戻り、**[関数]** で **[関数を追加]** ドロップダウンを選択して、関数を関数リストに追加します。

1. **[保存]** を選択してリゾルバーを更新します。

------
#### [ CLI ]

**関数を追加するには**
+ `[create-function](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-function.html)` コマンドを使用してパイプラインリゾルバー用の関数を作成します。

  この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

  1. API の `api-id` です。

  1.  AWS AppSync コンソール`name`の 関数の 。

  1. `data-source-name`、すなわち関数で使用されるデータソースの名前。すでに作成され、 AWS AppSync サービス内の GraphQL API にリンクされている必要があります。

  1. `runtime`、すなわち関数の環境と言語。JavaScript の場合、name は `APPSYNC_JS` で、runtime は `1.0.0` である必要があります。

  1. `code`、すなわち関数のリクエストハンドラーとレスポンスハンドラー。手動でも入力できますが、.txt ファイル (または同様の形式) に追加して引数として渡すほうがはるかに簡単です。
**注記**  
クエリコードは引数として渡されるファイルにあります。  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Performs a scan on the dynamodb data source
      */
     export function request(ctx) {
       return { operation: 'Scan' };
     }
     
     /**
      * return a list of scanned post items
      */
     export function response(ctx) {
       return ctx.result.items;
     }
     ```

  コマンドの例は、次のようになります。

  ```
  aws appsync create-function \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --name get_posts_func_1 \
  --data-source-name table-for-posts \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file://~/path/to/file/{filename}.{fileType}
  ```

  出力は CLI に返されます。例を示します。

  ```
  {
      "functionConfiguration": {
          "functionId": "ejglgvmcabdn7lx75ref4qeig4",
          "functionArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/functions/ejglgvmcabdn7lx75ref4qeig4",
          "name": "get_posts_func_1",
          "dataSourceName": "table-for-posts",
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```
**注記**  
`functionId` は、必ずどこかに記録しておいてください。これは、リゾルバーに関数をアタッチする際に使用します。

**リゾルバーを作成するには**
+ `[create-resolver](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html)` コマンドを実行して `Query` のパイプライン関数を作成します。

  この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

  1. API の `api-id` です。

  1. `type-name`、すなわちスキーマ内の特別なオブジェクトタイプ (クエリ、ミューテーション、サブスクリプション)。

  1. `field-name`、すなわちリゾルバーをアタッチする特別なオブジェクトタイプ内のフィールドオペレーション。

  1. `kind`。ユニットまたはパイプラインリゾルバーを指定します。これを `PIPELINE` に設定すると、パイプライン関数が有効になります。

  1. `pipeline-config`、すなわちリゾルバーにアタッチする関数。関数の `functionId` 値がわかっていることを確認してください。リストの順序は重要です。

  1. `runtime`。以前は `APPSYNC_JS` (JavaScript) でした。`runtimeVersion` は現在、`1.0.0` です。

  1. `code`。before および after ステップハンドラーが含まれています。
**注記**  
クエリコードは引数として渡されるファイルにあります。  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       const { id, ...values } = ctx.args;
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({ id }),
         attributeValues: util.dynamodb.toMapValues(values),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  コマンドの例は、次のようになります。

  ```
  aws appsync create-resolver \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --type-name Query \
  --field-name getPost \
  --kind PIPELINE \
  --pipeline-config functions=ejglgvmcabdn7lx75ref4qeig4 \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  出力は CLI に返されます。例を示します。

  ```
  {
      "resolver": {
          "typeName": "Mutation",
          "fieldName": "getPost",
          "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation/resolvers/getPost",
          "kind": "PIPELINE",
          "pipelineConfig": {
              "functions": [
                  "ejglgvmcabdn7lx75ref4qeig4"
              ]
          },
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```

------
#### [ CDK ]

**ヒント**  
CDK を使用する前に、CDK の[公式ドキュメント](https://docs.aws.amazon.com/cdk/v2/guide/home.html)と CDK AWS AppSyncリファレンスを確認することをお勧めします。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
以下の手順では、特定のリソースを追加するために使用するスニペットの一般的な例のみを示しています。これは本番稼働用コードで機能するソリューションとなることを**意図したものではありません**。また、動作するアプリが既にあることを前提としています。

基本的なアプリには以下のものが必要です。

1. サービス import ディレクティブ

1. スキーマのコード

1. データソースジェネレーター

1. 関数コード

1. リゾルバーのコード

「[スキーマの設計](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html)」と「[データソースを追加する](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)」の各セクションによれば、スタックファイルには以下の形式の import ディレクティブが含まれます。

```
import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
```

**注記**  
前のセクションでは、 AWS AppSync コンストラクトをインポートする方法のみについて説明しました。実際のコードでは、アプリを実行するためだけにより多くのサービスをインポートする必要があります。この例では、非常にシンプルな CDK アプリを作成する場合、少なくとも DynamoDB テーブルであるデータソースとともに AWS AppSync サービスをインポートします。また、アプリをデプロイするには、いくつかの追加コンストラクトをインポートする必要があります。  

```
import * as cdk from 'aws-cdk-lib';
import * as appsync from 'aws-cdk-lib/aws-appsync';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
```
それぞれについて概説すると、次のようになります。  
`import * as cdk from 'aws-cdk-lib';`: これにより、CDK アプリとスタックなどのコンストラクトを定義できます。また、メタデータの操作など、アプリケーションに役立つユーティリティ関数もいくつか含まれています。このインポートディレクティブには精通しているものの、cdk コアライブラリがここで使用される理由が不明の場合は、「[マイグレーション](https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html)」ページを参照してください。
`import * as appsync from 'aws-cdk-lib/aws-appsync';`: これにより [AWS AppSync](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html) サービスがインポートされます。
`import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';`: これにより [DynamoDB サービス](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb-readme.html)がインポートされます。
`import { Construct } from 'constructs';`: ルート [コンストラクト](https://docs.aws.amazon.com/cdk/v2/guide/constructs.html)を定義するにはこれが必要です。

インポートの種類は、呼び出すサービスによって異なります。例については、CDK のドキュメントを参照することをお勧めします。ページ上部のスキーマは、CDK アプリでは `.graphql` ファイルとして個別のファイルになります。スタックファイルでは、次の形式でスキーマを新しい GraphQL に関連付けることができます。

```
const add_api = new appsync.GraphqlApi(this, 'graphQL-example', {
  name: 'my-first-api',
  schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema.graphql')),
});
```

**注記**  
スコープ `add_api` では、`new` キーワードの後に `appsync.GraphqlApi(scope: Construct, id: string , props: GraphqlApiProps)` を続けて新しい GraphQL API が追加されています。スコープは `this` で、CFN ID が `graphQL-example` で、props は `my-first-api` (コンソールに表示される API の名前) および `schema.graphql` (スキーマファイルへの絶対パス) です。

データソースを追加するには、まずデータソースをスタックに追加する必要があります。次に、ソース固有のメソッドを使用して GraphQL API に関連付ける必要があります。この関連付けは、リゾルバー関数を作成したときに行われます。その間に、`dynamodb.Table` を使用して DynamoDB テーブルを作成する例を見てみましょう。

```
const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
  partitionKey: {
    name: 'id',
    type: dynamodb.AttributeType.STRING,
  },
});
```

**注記**  
この例でこれを使用すると、CFN ID が `posts-table` で、パーティションキーが `id (S)` という新しい DynamoDB テーブルが追加されます。

次に、スタックファイルにリゾルバーを実装する必要があります。DynamoDB テーブル内のすべての項目をスキャンする簡単なクエリの例を以下に示します。

```
const add_func = new appsync.AppsyncFunction(this, 'func-get-posts', {
  name: 'get_posts_func_1',
  add_api,
  dataSource: add_api.addDynamoDbDataSource('table-for-posts', add_ddb_table),
  code: appsync.Code.fromInline(`
      export function request(ctx) {
        return { operation: 'Scan' };
      }

      export function response(ctx) {
        return ctx.result.items;
      }
  `),
  runtime: appsync.FunctionRuntime.JS_1_0_0,
});

new appsync.Resolver(this, 'pipeline-resolver-get-posts', {
  add_api,
  typeName: 'Query',
  fieldName: 'getPost',
  code: appsync.Code.fromInline(`
      export function request(ctx) {
        return {};
      }

      export function response(ctx) {
        return ctx.prev.result;
      }
 `),
  runtime: appsync.FunctionRuntime.JS_1_0_0,
  pipelineConfig: [add_func],
});
```

**注記**  
最初に、`add_func` という関数を作成しました。この作成順序は少し直観に反するような印象を持つかもしれませんが、リゾルバー自体を作成する前に、パイプラインリゾルバーで関数を作成する必要があります。関数は次の形式に従います。  

```
AppsyncFunction(scope: Construct, id: string, props: AppsyncFunctionProps)
```
スコープは `this`で、CFN ID が `func-get-posts` で、props には実際に関数の詳細が含まれています。props 内には以下が含まれています。  
 AWS AppSync コンソールに存在する関数`name`の (`get_posts_func_1`)。
以前に作成した GraphQL API (`add_api`)。
データソース。これは、データソースを GraphQL API 値にリンクし、それを関数にアタッチするポイントです。作成したテーブル (`add_ddb_table`) を取得し、`GraphqlApi` メソッド ([https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.GraphqlApi.html#addwbrdynamowbrdbwbrdatawbrsourceid-table-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.GraphqlApi.html#addwbrdynamowbrdbwbrdatawbrsourceid-table-options)) のいずれかを使用して GraphQL API (`add_api`) にアタッチします。ID 値 (`table-for-posts`) は AWS AppSync コンソールに表示されるデータソースの名前です。ソース固有のメソッドの一覧については、次のページを参照してください。  
[ DynamoDbDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.DynamoDbDataSource.html) 
 [ EventBridgeDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.EventBridgeDataSource.html) 
 [ HttpDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.HttpDataSource.html) 
 [ LambdaDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.LambdaDataSource.html) 
 [ NoneDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.NoneDataSource.html) 
 [ OpenSearchDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.OpenSearchDataSource.html) 
 [ RdsDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.RdsDataSource.html) 
コードには関数のリクエストハンドラーとレスポンスハンドラーが含まれており、シンプルなスキャンを実行し、結果を返します。
ランタイムでは、APPSYNC\$1JS ランタイムバージョン 1.0.0 を使用することを指定しています。現在 APPSYNC\$1JS で使用できるのはこのバージョンだけであることに注意してください。
次に、関数をパイプラインリゾルバーにアタッチする必要があります。リゾルバーは次の形式で作成しています。  

```
Resolver(scope: Construct, id: string, props: ResolverProps)
```
スコープは `this`で、CFN ID が `pipeline-resolver-get-posts` で、props には実際に関数の詳細が含まれています。props 内には以下が含まれています。  
以前に作成した GraphQL API (`add_api`)。
特別なオブジェクトタイプ名。これはクエリオペレーションであり、`Query` 値を追加しただけです。
フィールド名 (`getPost`) は、`Query` タイプのスキーマ内にあるフィールドの名前です。
コードには before ハンドラーと after ハンドラーが含まれています。この例では、関数がオペレーションを実行した後の context 内の結果を返すだけです。
ランタイムでは、APPSYNC\$1JS ランタイムバージョン 1.0.0 を使用することを指定しています。現在 APPSYNC\$1JS で使用できるのはこのバージョンだけであることに注意してください。
パイプライン config には、作成した関数 (`add_func`) への参照が含まれています。

------

この例で何が起こったかを要約すると、リクエストとレスポンスハンドラーを実装した AWS AppSync 関数が表示されました。この関数はデータソースとやりとりする役割を持っています。リクエストハンドラーは に`Scan`オペレーションを送信し AWS AppSync、DynamoDB データソースに対して実行するオペレーションを指示します。レスポンスハンドラーは項目のリスト (`ctx.result.items`) を返します。その後、項目のリストは `Post` GraphQL タイプに自動的にマッピングされました。

## 基本的なミューテーションリゾルバーの作成
<a name="creating-basic-mutation-resolvers-js"></a>

このセクションでは、基本的なミューテーションリゾルバーを作成する方法を説明します。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[スキーマ]** を選択します。

1. **[リゾルバー]** セクションと**[ミューテーションタイプ]** で、フィールドの横にある **[アタッチ]** を選択します。
**注記**  
この例では、`createPost` のリゾルバーをアタッチすることで、`Post` オブジェクトをテーブルに追加します。前のセクションと同じ DynamoDB テーブルを使用していると仮定します。そのパーティションキーは `id` に設定されており、空です。

1. **[リゾルバーをアタッチ]** ページの **[リゾルバータイプ]** で、[`pipeline resolvers`] を選択します。リゾルバーの詳細を確認する場合は、[こちら](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html)を参照してください。**[リゾルバーランタイム]** では、[`APPSYNC_JS`] を選択して JavaScript ランタイムを有効化します。

1. この API の[キャッシュ](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html)は有効にできます。現時点では、この機能をオフにすることをお勧めします。**[作成]** を選択します。

1. **[関数の追加]** を選択して、**[新しい関数を作成]** を選択します。代わりに **[関数の作成]** ボタンが表示されて選択できる場合もあります。

   1.  データソースを選択します。これは、ミューテーション時にデータを操作する際のソースになります。

   1. `Function name` を入力します。

   1. **[関数コード]** で、関数の動作を実装する必要があります。これはミューテーションであるため、リクエストにより、呼び出されたデータソースに対してある程度状態が変化するオペレーションが実行されると理想的です。結果はレスポンス関数によって処理されます。
**注記**  
`createPost` はパラメータがデータとして含まれているテーブルに新しい `Post` ものを追加します (入れます)。次のように追加します。  

      ```
      import { util } from '@aws-appsync/utils';
      
      /**
       * Sends a request to `put` an item in the DynamoDB data source
       */
      export function request(ctx) {
        return {
          operation: 'PutItem',
          key: util.dynamodb.toMapValues({id: util.autoId()}),
          attributeValues: util.dynamodb.toMapValues(ctx.args.input),
        };
      }
      
      /**
       * returns the result of the `put` operation
       */
      export function response(ctx) {
        return ctx.result;
      }
      ```
このステップでは、`request` と `response` の 2 つの関数を追加しました。  
`request`: リクエストハンドラーはコンテキストを引数として受け入れます。リクエストハンドラーの return ステートメントは、組み込みの DynamoDB オペレーションである [https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-putitem](https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-putitem) コマンドを実行します (例については、[こちら](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-2.html)または[こちら](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.WritingData)を参照してください)。`PutItem` このコマンドは、パーティション `key` 値 (`util.autoid()` によって自動的に生成) とコンテキストの引数の入力による `attributes` (リクエストで渡される値) を取得して、`Post` オブジェクトを DynamoDB テーブルに追加します。`key` は、`id` で、`attributes` は `date` および `title` フィールド引数です。どちらも [https://docs.aws.amazon.com//appsync/latest/devguide/dynamodb-helpers-in-util-dynamodb-js.html#utility-helpers-in-toMap-js](https://docs.aws.amazon.com//appsync/latest/devguide/dynamodb-helpers-in-util-dynamodb-js.html#utility-helpers-in-toMap-js)ヘルパーを経由して実行され、DynamoDB テーブルを使用します。
`response`: レスポンスは、更新されたコンテキストを受け入れ、リクエストハンドラーの結果を返します。

   1. 完了したら、**[作成]** を選択します。

1. リゾルバー画面に戻り、**[関数]** で **[関数を追加]** ドロップダウンを選択して、関数を関数リストに追加します。

1. **[保存]** を選択してリゾルバーを更新します。

------
#### [ CLI ]

**関数を追加するには**
+ `[create-function](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-function.html)` コマンドを使用してパイプラインリゾルバー用の関数を作成します。

  この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

  1. API の `api-id` です。

  1.  AWS AppSync コンソール`name`の 関数の 。

  1. `data-source-name`、すなわち関数で使用されるデータソースの名前。すでに作成され、 AWS AppSync サービス内の GraphQL API にリンクされている必要があります。

  1. `runtime`、すなわち関数の環境と言語。JavaScript の場合、name は `APPSYNC_JS` で、runtime は `1.0.0` である必要があります。

  1. `code`、すなわち関数のリクエストハンドラーとレスポンスハンドラー。手動でも入力できますが、.txt ファイル (または同様の形式) に追加して引数として渡すほうがはるかに簡単です。
**注記**  
クエリコードは引数として渡されるファイルにあります。  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({id: util.autoId()}),
         attributeValues: util.dynamodb.toMapValues(ctx.args.input),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  コマンドの例は、次のようになります。

  ```
  aws appsync create-function \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --name add_posts_func_1 \
  --data-source-name table-for-posts \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  出力は CLI に返されます。例を示します。

  ```
  {
      "functionConfiguration": {
          "functionId": "vulcmbfcxffiram63psb4dduoa",
          "functionArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/functions/vulcmbfcxffiram63psb4dduoa",
          "name": "add_posts_func_1",
          "dataSourceName": "table-for-posts",
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output foes here"
      }
  }
  ```
**注記**  
`functionId` は、必ずどこかに記録しておいてください。これは、リゾルバーに関数をアタッチする際に使用します。

**リゾルバーを作成するには**
+ `[create-resolver](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html)` コマンドを実行して `Mutation` のパイプライン関数を作成します。

  この特定のコマンドでは、いくつかのパラメータを入力する必要があります。

  1. API の `api-id` です。

  1. `type-name`、すなわちスキーマ内の特別なオブジェクトタイプ (クエリ、ミューテーション、サブスクリプション)。

  1. `field-name`、すなわちリゾルバーをアタッチする特別なオブジェクトタイプ内のフィールドオペレーション。

  1. `kind`。ユニットまたはパイプラインリゾルバーを指定します。これを `PIPELINE` に設定すると、パイプライン関数が有効になります。

  1. `pipeline-config`、すなわちリゾルバーにアタッチする関数。関数の `functionId` 値がわかっていることを確認してください。リストの順序は重要です。

  1. `runtime`。以前は `APPSYNC_JS` (JavaScript) でした。`runtimeVersion` は現在、`1.0.0` です。

  1. `code`。before および after ステップが含まれています。
**注記**  
クエリコードは引数として渡されるファイルにあります。  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       const { id, ...values } = ctx.args;
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({ id }),
         attributeValues: util.dynamodb.toMapValues(values),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  コマンドの例は、次のようになります。

  ```
  aws appsync create-resolver \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --type-name Mutation \
  --field-name createPost \
  --kind PIPELINE \
  --pipeline-config functions=vulcmbfcxffiram63psb4dduoa \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  出力は CLI に返されます。例を示します。

  ```
  {
      "resolver": {
          "typeName": "Mutation",
          "fieldName": "createPost",
          "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation/resolvers/createPost",
          "kind": "PIPELINE",
          "pipelineConfig": {
              "functions": [
                  "vulcmbfcxffiram63psb4dduoa"
              ]
          },
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```

------
#### [ CDK ]

**ヒント**  
CDK を使用する前に、CDK の[公式ドキュメント](https://docs.aws.amazon.com/cdk/v2/guide/home.html)と CDK AWS AppSyncリファレンスを確認することをお勧めします。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
以下の手順では、特定のリソースを追加するために使用するスニペットの一般的な例のみを示しています。これは本番稼働用コードで機能するソリューションとなることを**意図したものではありません**。また、動作するアプリが既にあることを前提としています。
+ 同じプロジェクトに属していると仮定して、ミューテーションを行うには、クエリのようにスタックファイルにミューテーションを追加できます。以下は、テーブルに新しい `Post` を追加するミューテーションの修正済み関数とリゾルバーです。

  ```
  const add_func_2 = new appsync.AppsyncFunction(this, 'func-add-post', {
    name: 'add_posts_func_1',
    add_api,
    dataSource: add_api.addDynamoDbDataSource('table-for-posts-2', add_ddb_table),
        code: appsync.Code.fromInline(`
            export function request(ctx) {
              return {
                operation: 'PutItem',
                key: util.dynamodb.toMapValues({id: util.autoId()}),
                attributeValues: util.dynamodb.toMapValues(ctx.args.input),
              };
            }
  
            export function response(ctx) {
              return ctx.result;
            }
        `), 
    runtime: appsync.FunctionRuntime.JS_1_0_0,
  });
  
  new appsync.Resolver(this, 'pipeline-resolver-create-posts', {
    add_api,
    typeName: 'Mutation',
    fieldName: 'createPost',
        code: appsync.Code.fromInline(`
            export function request(ctx) {
              return {};
            }
  
            export function response(ctx) {
              return ctx.prev.result;
            }
        `),
    runtime: appsync.FunctionRuntime.JS_1_0_0,
    pipelineConfig: [add_func_2],
  });
  ```
**注記**  
このミューテーションとクエリの構造は似ているため、ここではミューテーションを実行するために行った変更について説明します。  
この関数では、テーブルに `Posts` を追加していることを反映して CFN ID を `func-add-post` に、名前を `add_posts_func_1` に変更しました。データソースでは、 `addDynamoDbDataSource` メソッドで必要な`table-for-posts-2`ため、 AWS AppSync コンソールでテーブル (`add_ddb_table`) に新しい関連付けを行いました。この新しい関連付けは、以前に作成したのと同じテーブルをまだ使用していますが、 AWS AppSync コンソールには 2 つの接続があります。1 つはクエリ用で`table-for-posts`、もう 1 つはミューテーション用です`table-for-posts-2`。コードは、`id` 値を自動的に生成し、残りのフィールドのクライアントの入力を受け入れることで、`Post` を追加するように変更されました。  
リゾルバーでは、テーブルに `Posts` を追加していることを反映して ID 値を `pipeline-resolver-create-posts` に変更しました。スキーマのミューテーションを反映するため、タイプ名が `Mutation` に変更され、名前が `createPost` に変更されました。パイプラインの config は、新しいミューテーション関数 `add_func_2` に設定されました。

------

この例で何が起こっているかを要約すると、 は `createPost`フィールドで定義された引数を GraphQL スキーマから DynamoDB オペレーション AWS AppSync に自動的に変換します。`util.autoId()` ヘルパーを使用して自動的に作成される `id` のキーを使用して、DynamoDB にレコードが保存されます。 AWS AppSync コンソールで行われたリクエストまたはそれ以外のリクエストからコンテキスト引数 (`ctx.args.input`) に渡す他のすべてのフィールドは、テーブルの属性として保存されます。キーと属性は両方とも、`util.dynamodb.toMapValues(values)` ヘルパーを使用して互換性のある DynamoDB 形式に自動的にマッピングされます。

AWS AppSync は、リゾルバーを編集するためのテストおよびデバッグワークフローもサポートしています。モック `context` オブジェクトを使用して、呼び出す前にテンプレートでの変換後の値を確認できます。また、クエリを実行する際にデータソースへのリクエスト全体をインタラクティブに表示することもできます。詳細については、「[リゾルバーのテストとデバッグ (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/test-debug-resolvers-js.html)」および「[モニタリングとロギング](https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html#aws-appsync-monitoring)」を参照してください。

## 高度なリゾルバー
<a name="advanced-resolvers-js"></a>

「[スキーマの設計](designing-your-schema.md#aws-appsync-designing-your-schema)」のオプションのページネーションセクションに従っている場合でも、ページネーションを利用するにはリゾルバーをリクエストに追加する必要があります。この例では、`getPosts` と呼ばれるクエリページネーションを使用して、リクエストされた内容の一部だけを一度に返します。このフィールドのリゾルバーのコードは以下のようになります。

```
/**
 * Performs a scan on the dynamodb data source
 */
export function request(ctx) {
  const { limit = 20, nextToken } = ctx.args;
  return { operation: 'Scan', limit, nextToken };
}

/**
 * @returns the result of the `put` operation
 */
export function response(ctx) {
  const { items: posts = [], nextToken } = ctx.result;
  return { posts, nextToken };
}
```

リクエストでは、リクエストのコンテキストを渡します。この例では、`limit` は *20* で、最初のクエリでは最大 20 `Posts` を返します。`nextToken` カーソルはデータソースの最初の `Post` エントリに固定されています。これらは args に渡されます。その後、リクエストは最初の `Post` からスキャン制限数までスキャンを実行します。データソースは結果をコンテキストに保存し、その結果はレスポンスに渡されます。レスポンスは取得した `Posts` を返し、`nextToken` が制限数直後の `Post` エントリに設定されます。次のリクエストも送信され、まったく同じ処理が行われますが、最初のクエリの直後のオフセットから開始されます。これらの種類のリクエストは、並列ではなくシーケンシャルに行われることに注意してください。

# AWS AppSync でのリゾルバーのテストとデバッグ (JavaScript)
<a name="test-debug-resolvers-js"></a>

AWS AppSync は、データソースに対して GraphQL フィールドでリゾルバーを実行します。パイプラインリゾルバーを操作する場合、関数はデータソースとやりとりします。「[JavaScript リゾルバーの概要](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)」で説明したように、関数は JavaScript で記述され、ランタイムで実行されるリクエストハンドラーとレスポンスハンドラーを使用してデータソースと通信します`APPSYNC_JS`。これにより、ユーザーはカスタムロジック条件を提供でき、データソースと通信する前後にロジックおよび条件を適用できます。

デベロッパーがこれらのリゾルバーを記述、テスト、デバッグできるように、 AWS AppSync コンソールには、モックデータを含む GraphQL リクエストとレスポンスを個々のフィールドリゾルバーに作成するためのツールも用意されています。さらに、 AWS AppSync コンソールでクエリ、ミューテーション、サブスクリプションを実行し、Amazon CloudWatch からのリクエスト全体の詳細なログストリームを表示できます。ログストリームにはデータソースからの結果も含まれています。

## モックデータを使用したテスト
<a name="testing-with-mock-data-js"></a>

GraphQL リゾルバーが呼び出されるときに、そのリゾルバーには、リクエストに関する情報が含まれている `context` オブジェクトが含まれています。このオブジェクトには、クライアントからの引数、ID 情報、および親 GraphQL フィールドからのデータが含まれています。また、データソースからの結果も含まれていて、それをレスポンスハンドラーで使用できます。この構造およびプログラミング時に使用可能なヘルパーユーティリティの詳細については、「[リゾルバーコンテキストオブジェクトリファレンス](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)」を参照してください。

リゾルバー関数を記述または編集する場合に、*モック*または*コンテキストのテスト*の オブジェクトをコンソールエディタに渡すことができます。これにより、実際にデータソースに対して実行することなく、リクエストとレスポンスハンドラーの両方でどのように評価されるかを確認できます。例えば、テストの `firstname: Shaggy` 引数を渡して、テンプレートのコードで `ctx.args.firstname` を使用している場合にその引数がどのように評価されるかを確認できます。任意のユーティリティヘルパー (`util.autoId()`、`util.time.nowISO8601()` など) での評価をテストすることもできます。

### リゾルバーのテスト
<a name="test-a-resolver-js"></a>

この例では、 AWS AppSync コンソールを使用してリゾルバーをテストします。

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[関数]** を選択します。

1. 既存の関数を選択します。

1. **[関数の更新]** ページの上部で、**[テストコンテキストを選択]** を選択し、**[新しいコンテキストを作成]** を選択します。

1. サンプルコンテキストオブジェクトを選択するか、下の **[テストコンテキストを設定]** ウィンドウで JSON を手動で入力します。

1. **テキストコンテキスト名**を入力します。

1. **[保存]** ボタンを選択します。

1. この模擬コンテキストオブジェクトを使用してリゾルバーを評価するには、[**Run Test**] を選択します。

例えば、オブジェクトに対して自動 ID 生成を使用して Amazon DynamoDB に保存する `Dog` の GraphQL タイプを保存するアプリケーションがあるとします。また、一部の値を GraphQL ミューテーションの引数から書き込み、レスポンスが特定の 1 人のユーザーにのみ表示されるようにします。次のスニペットがスキーマがどのようになっているかを示します。

```
type Dog {
  breed: String
  color: String
}

type Mutation {
  addDog(firstname: String, age: Int): Dog
}
```

 AWS AppSync 関数を記述し、リ`addDog`ゾルバーに追加してミューテーションを処理できます。 AWS AppSync 関数をテストするには、次の例のようにコンテキストオブジェクトを入力します。次の例には、クライアントから引数として `name` と `age` があり、`identity` オブジェクトに入力されている `username` があります。

```
{
    "arguments" : {
        "firstname": "Shaggy",
        "age": 4
    },
    "source" : {},
    "result" : {
        "breed" : "Miniature Schnauzer",
        "color" : "black_grey"
    },
    "identity": {
        "sub" : "uuid",
        "issuer" : " https://cognito-idp.{region}.amazonaws.com/{userPoolId}",
        "username" : "Nadia",
        "claims" : { },
        "sourceIp" :[  "x.x.x.x" ],
        "defaultAuthStrategy" : "ALLOW"
    }
}
```

次のコードを使用して AWS AppSync 関数をテストできます。

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({ id: util.autoId() }),
    attributeValues: util.dynamodb.toMapValues(ctx.args),
  };
}

export function response(ctx) {
  if (ctx.identity.username === 'Nadia') {
    console.log("This request is allowed")
    return ctx.result;
  }
  util.unauthorized();
}
```

評価後のリクエストとレスポンスハンドラーには、テストコンテキストオブジェクトからのデータと、`util.autoId()` から生成された値があります。また、`username` を `Nadia` 以外の値に変更した場合は、認可チェックが失敗するため、結果は返されません。きめ細かなアクセス制御の詳細については、「[認可のユースケース](security-authorization-use-cases.md#aws-appsync-security-authorization-use-cases)」を参照してください。

### AWS AppSync APIs を使用したリクエストハンドラーとレスポンスハンドラーのテスト
<a name="testing-with-appsync-api-js"></a>

`EvaluateCode` API コマンドを使用して、モックデータを使用してコードをリモートでテストできます。コマンドを使い始めるには、ポリシーに `appsync:evaluateMappingCode` アクセス許可を追加していることを確認してください。例えば、次のようになります。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appsync:evaluateCode",
            "Resource": "arn:aws:appsync:us-east-1:111122223333:*"
        }
    ]
}
```

------

[AWS CLI](https://aws.amazon.com/cli/) または [AWS SDK](https://aws.amazon.com/tools/) を使用してコマンドを活用できます。例えば、前のセクションで `Dog` スキーマとその AWS AppSync 関数のリクエストおよびレスポンスハンドラーを見てみましょう。ローカルステーションの CLI を使用して、コードを `code.js` という名前のファイルに保存し、`context` オブジェクトを `context.json` という名前のファイルに保存します。シェルから次のコマンドを実行します。

```
$ aws appsync evaluate-code \
  --code file://code.js \
  --function response \
  --context file://context.json \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0
```

レスポンスには、ハンドラーから返されたペイロードを含む `evaluationResult` が含まれます。また、評価中にハンドラーによって生成されたログのリストを保持する `logs` オブジェクトも含まれています。これにより、コード実行のデバッグが容易になり、評価に関する情報を確認してトラブルシューティングに役立てることができます。例えば、次のようになります。

```
{
    "evaluationResult": "{\"breed\":\"Miniature Schnauzer\",\"color\":\"black_grey\"}",
    "logs": [
        "INFO - code.js:13:5: \"This request is allowed\""
    ]
}
```

`evaluationResult` は JSON として解析でき、以下を実現します。

```
{
  "breed": "Miniature Schnauzer",
  "color": "black_grey"
}
```

SDK を使用すると、お気に入りのテストスイートのテストを簡単に組み込んで、ハンドラーの動作を検証できます。[Jest テストフレームワーク](https://jestjs.io/)を使用してテストを作成することをお勧めしますが、どのテストスイートでも問題ありません。次のスニペットは、仮説検証の実行を示しています。評価レスポンスは有効な JSON であることを想定しているので、`JSON.parse`を使用して文字列レスポンスから JSON を取得することに注意してください。

```
const AWS = require('aws-sdk')
const fs = require('fs')
const client = new AWS.AppSync({ region: 'us-east-2' })
const runtime = {name:'APPSYNC_JS',runtimeVersion:'1.0.0')

test('request correctly calls DynamoDB', async () => {
  const code = fs.readFileSync('./code.js', 'utf8')
  const context = fs.readFileSync('./context.json', 'utf8')
  const contextJSON = JSON.parse(context)
  
  const response = await client.evaluateCode({ code, context, runtime, function: 'request' }).promise()
  const result = JSON.parse(response.evaluationResult)
  
  expect(result.key.id.S).toBeDefined()
  expect(result.attributeValues.firstname.S).toEqual(contextJSON.arguments.firstname)
})
```

 これにより、次のような結果が得られます。

```
Ran all test suites.
> jest

PASS ./index.test.js
✓ request correctly calls DynamoDB (543 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 totalTime: 1.511 s, estimated 2 s
```

## ライブクエリのデバッグ
<a name="debugging-a-live-query-js"></a>

本番アプリケーションをデバッグするためのend-to-endのテストとログ記録に代わるものはありません。 AWS AppSync では、Amazon CloudWatch を使用してエラーとリクエストの詳細全体をログ記録できます。さらに、 AWS AppSync コンソールを使用して、各リクエストの GraphQL クエリ、ミューテーション、サブスクリプション、ライブストリームログデータをテストし、クエリエディタに戻し、リアルタイムでデバッグできます。サブスクリプションに関して表示されるログは接続時の情報です。

これを実行するには、「[モニタリングとロギング](monitoring.md#aws-appsync-monitoring)」で説明しているように、Amazon CloudWatch Logs を事前に有効にしておく必要があります。次に、 AWS AppSync コンソールで**クエリ**タブを選択し、有効な GraphQL クエリを入力します。右下のセクションで、**[ログ]** ウィンドウをクリックしてドラッグし、ログビューを開きます。ページの上部にある再生矢印アイコンを選択して GraphQL クエリを実行します。しばらくすると、そのオペレーションのリクエストとレスポンスの完全なログが、このセクションにストリーミングされ、コンソールで表示できます。

# AWS AppSync でのパイプラインリゾルバーの設定と使用 (JavaScript)
<a name="pipeline-resolvers-js"></a>

AWS AppSync は GraphQL フィールドでリゾルバーを実行します。場合によっては、アプリケーションは 1 つの GraphQL フィールドを解決するために複数のオペレーションを実行する必要があります。パイプラインリゾルバーを使用すると、開発者は関数と呼ばれるオペレーションを構成して順番に実行できます。パイプラインリゾルバーは、たとえば、フィールドのデータを取得する前に承認チェックを実行する必要があるアプリケーションに便利です。

JavaScript パイプラインリゾルバーのアーキテクチャの詳細については、「[JavaScript リゾルバーの概要](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html#anatomy-of-a-pipeline-resolver-js)」を参照してください。

## ステップ 1: パイプラインリゾルバーを作成する
<a name="create-a-pipeline-resolver-js"></a>

 AWS AppSync コンソールで、**スキーマ**ページに移動します。

以下のスキーマを保存します。

```
schema {
    query: Query
    mutation: Mutation
}

type Mutation {
    signUp(input: Signup): User
}

type Query {
    getUser(id: ID!): User
}

input Signup {
    username: String!
    email: String!
}

type User {
    id: ID!
    username: String
    email: AWSEmail
}
```

パイプラインリゾルバーを**ミューテーション**タイプの **SignUp** フィールドに書き込みます。右側の **[ミューテーション]** タイプに入力し、[`signUp` ミューテーション] フィールドの横の **[アタッチ]** を選択します。リゾルバーを `pipeline resolver` および `APPSYNC_JS` ランタイムに設定し、リゾルバーを作成します。

パイプラインリゾルバーは、最初に E メールアドレスの入力を検証してからシステムにユーザーを保存することで、ユーザーをサインアップします。E メールの検証を **validateEmail** 関数内にカプセル化し、ユーザーの保存を **saveUser** 関数内にカプセル化します。**validateEmail** 関数が最初に実行され、E メールが有効であれば、**saveUser** 関数が実行されます。

実行フローは以下のようになります。

1. Mutation.SignUp リゾルバーリクエストハンドラー

1. validateEmail 関数

1. saveUser 関数

1. Mutation.SignUp リゾルバーレスポンスハンドラー

API の他のリゾルバーで **validateEmail** 関数を再利用することが多いため、GraphQL フィールド間でアクセス先の `ctx.args` が変わるのを避けるとします。この場合、代わりに `ctx.stash` を使用して、`signUp(input: Signup)` 入力フィールド引数からの email 属性を保存できます。

リクエスト関数とレスポンス関数を置き換えてリゾルバーコードを更新してください。

```
export function request(ctx) {
    ctx.stash.email = ctx.args.input.email
    return {};
}

export function response(ctx) {
    return ctx.prev.result;
}
```

**[作成]** または **[保存]** を選択してリゾルバーを更新します。

## ステップ 2: 関数を作成する
<a name="create-a-function-js"></a>

パイプラインリゾルバーページの **[関数]** セクションで、**[関数の作成]** をクリックして、**[新しい関数の作成]** をクリックします。リゾルバーページを経由せずに関数を作成することもできます。これを行うには、 AWS AppSync コンソールで**関数**ページに移動します。**[関数の作成]** ボタンを選択します。E メールが有効であり特定のドメインからのものかどうかをチェックする関数を作成しましょう。E メールが無効な場合、この関数はエラーを発生させます。それ以外の場合、渡された入力をすべて転送します。

**NONE** タイプのデータソースを作成したことを確認してください。**[データソース名]** リストでこのデータソースを選択します。**関数名**として、「`validateEmail`」と入力します。**関数コード**領域で、次のスニペットですべてを上書きします。

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { email } = ctx.stash;
  const valid = util.matches(
    '^[a-zA-Z0-9_.+-]+@(?:(?:[a-zA-Z0-9-]+\.)?[a-zA-Z]+\.)?(myvaliddomain)\.com',
    email
  );
  if (!valid) {
    util.error(`"${email}" is not a valid email.`);
  }

  return { payload: { email } };
}

export function response(ctx) {
  return ctx.result;
}
```

選択内容を確認し、**[作成]** を選択します。これで、**validateEmail** 関数が作成されました。次のコードでこれらの手順を繰り返し、**saveUser** 関数を作成します (わかりやすくするため、**NONE** データソースを使用し、関数が実行された後にユーザーがシステムに保存されたものとしています。):

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  return ctx.prev.result;
}

export function response(ctx) {
  ctx.result.id = util.autoId();
  return ctx.result;
}
```

これで、**saveUser** 関数が作成されました。

## ステップ 3: パイプラインリゾルバーに関数を追加する
<a name="adding-a-function-to-a-pipeline-resolver-js"></a>

先ほど作成したパイプラインリゾルバーには関数が自動的に追加されています。そうでない場合や、**[関数]** ページから関数を作成した場合は、`signUp` リゾルバーページの **[関数を追加]** をクリックして、関数をアタッチできます。**validateEmail** と **saveUser** の両方の関数をリゾルバーに追加します。**validateEmail** 関数は **saveUser** 関数の前に配置する必要があります。関数を追加するときには、**上に移動**および**下に移動**オプションを使用して関数の実行順序を並べ替えることができます。変更を確認し、**[保存]** を選択します。

## ステップ 4: クエリを実行する
<a name="running-a-query-js"></a>

 AWS AppSync コンソールで、**クエリ**ページに移動します。Explorer で、ミューテーションを使用していることを確認します。そうでない場合は、ドロップダウンリストから [`Mutation`] を選択し、[`+`] を選択します。以下のクエリを入力します。

```
mutation {
  signUp(input: {email: "nadia@myvaliddomain.com", username: "nadia"}) {
    id
    username
  }
}
```

以下のように返されます。

```
{
  "data": {
    "signUp": {
      "id": "256b6cc2-4694-46f4-a55e-8cb14cc5d7fc",
      "username": "nadia"
    }
  }
}
```

これで、パイプラインリゾルバーを使用して、ユーザーをサインアップし、入力 E メールを検証できました。

# 基本クエリの作成 (VTL)
<a name="configuring-resolvers"></a>

**注記**  
現在、主に APPSYNC\$1JS ランタイムとそのドキュメントをサポートしています。[こちら](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html)にある APPSYNC\$1JS ランタイムとそのガイドの使用をご検討ください。

GraphQL リゾルバーは、タイプのスキーマのフィールドをデータソースに接続します。リゾルバーは、リクエストが受理されるメカニズムです。 AWS AppSync は、コードを記述することなく、スキーマからリゾルバーを自動的に作成して接続したり、スキーマを作成して既存のテーブルからリゾルバーに接続したりできます。

 AWS AppSync のリゾルバーは、JavaScript を使用して GraphQL 式をデータソースが使用できる形式に変換します。または、マッピングテンプレートを [Apache Velocity Template Language (VTL)](https://velocity.apache.org/engine/2.0/vtl-reference.html) で記述すると、GraphQL 表現をデータソースで使用できる形式に変換できます。

このセクションでは、VTL を使用してリゾルバーを設定する方法について説明します。リゾルバーを記述するための入門チュートリアル形式のプログラミングガイドは、[リゾルバーマッピングテンプレートプログラミングガイド](resolver-mapping-template-reference-programming-guide.md#aws-appsync-resolver-mapping-template-reference-programming-guide)に記載されています。プログラミング時に使用できるヘルパーユーティリティは、[リゾルバーマッピングテンプレートコンテキストリファレンス](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference)にあります。 AWS AppSync には、ゼロから編集またはオーサリングするときに使用できるテストおよびデバッグフローも組み込まれています。詳細については、「[リゾルバーのテストとデバッグ](test-debug-resolvers.md#aws-appsync-test-debug-resolvers)」を参照してください。

前述のチュートリアルを使用する前に、このガイドに従うことをお勧めします。

このセクションでは、リゾルバーを作成する方法、ミューテーション用のリゾルバーを追加する方法、詳細設定を使用する方法について説明します。

## 最初のリゾルバーを作成する
<a name="create-your-first-resolver"></a>

前のセクションの例に従うと、最初のステップとして、ご使用の `Query` タイプに合ったリゾルバーを作成します。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[スキーマ]** を選択します。

1. ページの右側には、**[リゾルバー]** というウィンドウがあります。このボックスには、ページの左側の **[スキーマ]** ウィンドウで定義されているタイプとフィールドのリストが含まれています。リゾルバーはフィールドにアタッチできます。たとえば、**[クエリ]** タイプで、`getTodos` フィールドの横にある **[アタッチ]** を選択します。

1. **[リゾルバーの作成]** ページで、「[データソースを追加する](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)」ガイドで作成したデータソースを選択します。**[マッピングテンプレートの設定]** ウィンドウでは、右側のドロップダウンリストを使用して汎用のリクエストおよびレスポンスのマッピングテンプレートを両方とも選択することも、独自のテンプレートを作成することもできます。
**注記**  
リクエストマッピングテンプレートとレスポンスマッピングテンプレートの組み合わせをユニットリゾルバーと呼びます。ユニットリゾルバーは通常、機械的なオペレーションを実行するためのものであるため、データソース数が少ない単一のオペレーションのみに使用することをおすすめします。より複雑なオペレーションには、複数のデータソースで複数のオペレーションを連続して実行できるパイプラインリゾルバーの使用をお勧めします。  
リクエストマッピングテンプレートとレスポンスマッピングテンプレートの違いの詳細については、「[ユニットリゾルバー](https://docs.aws.amazon.com//appsync/latest/devguide/resolver-mapping-template-reference-overview.html#unit-resolvers)」を参照してください。  
パイプラインリゾルバーの使用に関する詳細については、「[パイプラインリゾルバー](pipeline-resolvers.md#aws-appsync-pipeline-resolvers)」を参照してください。

1. 一般的なユースケースでは、 AWS AppSync コンソールには、データソースから項目を取得するために使用できる組み込みテンプレート (すべての項目クエリ、個々のルックアップなど) があります。たとえば、「[スキーマの設計](designing-your-schema.md#aws-appsync-designing-your-schema)」で使用したスキーマのシンプルバージョンでは、`getTodos` にページ分割がなく、項目を一覧表示するためのリクエストマッピングテンプレートは次のようになっていました。

   ```
   {
       "version" : "2017-02-28",
       "operation" : "Scan"
   }
   ```

1. リクエストに関連付けるレスポンスマッピングテンプレートが常に必要になります。コンソールには、リストの値をパススルーする次のようなデフォルトのテンプレートがあります。

   ```
   $util.toJson($ctx.result.items)
   ```

   この例では、項目のリストに対する `context` オブジェクト (`$ctx` としてエイリアスが作成された) の形式は `$context.result.items` です。GraphQL オペレーションが 1 つの項目を返す場合、 になります`$context.result`。 AWS AppSync は、レスポンスを適切にフォーマットするために、前述の関数など、一般的なオペレーション用のヘルパー`$util.toJson`関数を提供します。関数の完全なリストについては、「[リゾルバーのマッピングテンプレートのユーティリティリファレンス](resolver-util-reference.md#aws-appsync-resolver-mapping-template-util-reference)」を参照してください。

1. **[リゾルバーを保存]** を選択します。

------
#### [ API ]

1. [https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html](https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html) API を呼び出して、リゾルバーオブジェクトを作成します。

1. [https://docs.aws.amazon.com/appsync/latest/APIReference/API_UpdateResolver.html](https://docs.aws.amazon.com/appsync/latest/APIReference/API_UpdateResolver.html) API を呼び出して、リゾルバーのフィールドを変更できます。

------
#### [ CLI ]

1. [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html) コマンドを実行してリゾルバーを作成します。

   このコマンドには次の 6 つのパラメータを入力する必要があります。

   1. API の `api-id`。

   1. スキーマ内で変更するタイプの `type-name`。このコンソールの例では、`Query` です。

   1. タイプ内で変更するフィールドの `field-name`。このコンソールの例では、`getTodos` です。

   1. 「[データソースを追加する](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)」ガイドで作成したデータソースの `data-source-name`。

   1. `request-mapping-template`。リクエストの本文です。このコンソールの例では、次のようになります。

      ```
      {
          "version" : "2017-02-28",
          "operation" : "Scan"
      }
      ```

   1. `response-mapping-template`。リクエストの本文です。このコンソールの例では、次のようになります。

      ```
      $util.toJson($ctx.result.items)
      ```

   コマンドの例は、次のようになります。

   ```
   aws appsync create-resolver --api-id abcdefghijklmnopqrstuvwxyz --type-name Query --field-name getTodos --data-source-name TodoTable --request-mapping-template "{ "version" : "2017-02-28", "operation" : "Scan", }" --response-mapping-template ""$"util.toJson("$"ctx.result.items)"
   ```

   出力は CLI に返されます。例を示します。

   ```
   {
       "resolver": {
           "kind": "UNIT",
           "dataSourceName": "TodoTable",
           "requestMappingTemplate": "{ version : 2017-02-28, operation : Scan, }",
           "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Query/resolvers/getTodos",
           "typeName": "Query",
           "fieldName": "getTodos",
           "responseMappingTemplate": "$util.toJson($ctx.result.items)"
       }
   }
   ```

1. リゾルバーのフィールドおよび/またはマッピングテンプレートを変更するには、[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-resolver.html) コマンドを実行します。

   `api-id` パラメータを除いて、`create-resolver` コマンドで使用されたパラメータは、`update-resolver` コマンドの新しい値で上書きされます。

------

## ミューテーション用のリゾルバーの追加
<a name="adding-a-resolver-for-mutations"></a>

次のステップは、ご使用の `Mutation` タイプに合ったリゾルバーを作成することです。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[スキーマ]** を選択します。

1. **[ミューテーション]** タイプで、`addTodo` フィールドの横にある **[アタッチ]** を選択します。

1. **[リゾルバーの作成]** ページで、「[データソースを追加する](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)」ガイドで作成したデータソースを選択します。

1. このミューテーションでは DynamoDB に新しい項目を追加するため、**[マッピングテンプレートの設定]** ウィンドウでリクエストテンプレートを変更する必要があります。次のリクエストマッピングテンプレートを使用します。

   ```
   {
       "version" : "2017-02-28",
       "operation" : "PutItem",
       "key" : {
           "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
       },
       "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
   }
   ```

1. AWS AppSync は、 `addTodo`フィールドで定義された引数を GraphQL スキーマから DynamoDB オペレーションに自動的に変換します。上記の例では、ミューテーションの引数で `$ctx.args.id` として渡された `id` のキーを使用して、レコードが DynamoDB に保存されます。渡した他のすべてのフィールドは、`$util.dynamodb.toMapValuesJson($ctx.args)` を使用して自動的に DynamoDB 属性にマッピングされます。

   このリゾルバーでは、次のレスポンスマッピングテンプレートを使用します。

   ```
   $util.toJson($ctx.result)
   ```

   AWS AppSync は、リゾルバーを編集するためのテストワークフローとデバッグワークフローもサポートしています。モック `context` オブジェクトを使用して、呼び出す前にテンプレートでの変換後の値を確認できます。また、クエリを実行する際にデータソースへのリクエストの実行全体をインタラクティブに表示することもできます。詳細については、「[リゾルバーのテストとデバッグ](test-debug-resolvers.md#aws-appsync-test-debug-resolvers)」および「[モニタリングとロギング](monitoring.md#aws-appsync-monitoring)」を参照してください。

1. **[リゾルバーを保存]** を選択します。

------
#### [ API ]

API では、[[最初のリゾルバーを作成する]](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver) セクションのコマンドと、このセクションのパラメータの詳細を利用することで、これを行うこともできます。

------
#### [ CLI ]

CLI では、[[最初のリゾルバーを作成する]](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver) セクションのコマンドと、このセクションのパラメータの詳細を利用することで、これを行うこともできます。

------

この時点で、高度なリゾルバーを使用していない場合は、「[API の使用](using-your-api.md#aws-appsync-using-your-api)」で説明されているよう GraphQL API の使用を開始できます。

## 高度なリゾルバー
<a name="advanced-resolvers"></a>

「[スキーマの設計](designing-your-schema.md#aws-appsync-designing-your-schema)」でのサンプルスキーマの構築の「高度な機能」セクションに従ってページ分割スキャンを行う場合は、代わりに `getTodos` フィールドに次のリクエストテンプレートを使用します。

```
{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "limit": $util.defaultIfNull(${ctx.args.limit}, 20),
    "nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.nextToken, null))
}
```

このページ分割のユースケースでは、レスポンスマッピングに *cursor* (クライアントが次の開始ページを知るため) と結果セットの両方が含まれている必要があるため、レスポンスマッピングは単なるパススルーではありません。マッピングテンプレートは次のようになります。

```
{
    "todos": $util.toJson($context.result.items),
    "nextToken": $util.toJson($context.result.nextToken)
}
```

前述のレスポンスマッピングテンプレート内のフィールドは、`TodoConnection` 型で定義されているフィールドと一致している必要があります。

`Comments` テーブルがあり、`Todo` 型の comments フィールドを解決するリレーション (`[Comment]` の型を返す) の場合は、2 番目のテーブルに対してクエリを実行するマッピングテンプレートを使用できます。これを行うには、「[データソースをアタッチする](attaching-a-data-source.md#aws-appsync-getting-started-build-a-schema-from-scratch)」で説明しているように `Comments` テーブルのデータソースを作成しておく必要があります。

**注記**  
ここで 2 番目のテーブルに対するクエリオペレーションを使用しているのは、例を示すことのみを目的としています。代わりに、DynamoDB に対して別のオペレーションを使用できます。さらに、リレーションは GraphQL スキーマによって制御されるため、 AWS Lambda や Amazon OpenSearch Service などの別のデータソースからデータを取得できます。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[スキーマ]** を選択します。

1. **[Todo]** タイプで、`comments` フィールドの横にある **[アタッチ]** を選択します。

1. **[リゾルバーの作成]** ページで、**Comments** テーブルのデータソースを選択します。クイックスタートガイドの **Comments** テーブルのデフォルト名は `AppSyncCommentTable` ですが、指定した名前によって異なる場合があります。

1. リクエストマッピングテンプレートに次のスニペットを追加します。

   ```
   {
       "version": "2017-02-28",
       "operation": "Query",
       "index": "todoid-index",
       "query": {
           "expression": "todoid = :todoid",
           "expressionValues": {
               ":todoid": {
                   "S": $util.toJson($context.source.id)
               }
           }
       }
   }
   ```

1. `context.source` は、解決する現在のフィールドの親オブジェクトを参照します。この例では、`source.id` は個別の `Todo` オブジェクトを参照します。これはクエリ式に使用されます。

   次のようにパススルーのレスポンスマッピングテンプレートを使用できます。

   ```
   $util.toJson($ctx.result.items)
   ```

1. **[リゾルバーを保存]** を選択します。

1. 最後に、コンソールの **[スキーマ]** ページで、リゾルバーを `addComment` フィールドにアタッチして `Comments` テーブルのデータソースを指定します。この例のリクエストマッピングテンプレートは、引数としてコメントされる特定の `todoid` を含む単純な `PutItem` ですが、次のように `$utils.autoId()` ユーティリティを使用してコメントに対して一意なソートキーを作成します。

   ```
   {
       "version": "2017-02-28",
       "operation": "PutItem",
       "key": {
           "todoid": { "S": $util.toJson($context.arguments.todoid) },
           "commentid": { "S": "$util.autoId()" }
       },
       "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
   }
   ```

   次のようにパススルーレスポンステンプレートを使用します。

   ```
   $util.toJson($ctx.result)
   ```

------
#### [ API ]

API では、[[最初のリゾルバーを作成する]](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver) セクションのコマンドと、このセクションのパラメータの詳細を利用することで、これを行うこともできます。

------
#### [ CLI ]

CLI では、[[最初のリゾルバーを作成する]](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver) セクションのコマンドと、このセクションのパラメータの詳細を利用することで、これを行うこともできます。

------

# ダイレクト Lambda リゾルバー (VTL) を使用した VTL マッピングテンプレートの無効化
<a name="direct-lambda-reference"></a>

**注記**  
現在、主に APPSYNC\$1JS ランタイムとそのドキュメントをサポートしています。[こちら](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html) で APPSYNC\$1JS ランタイムとそのガイドの使用をご検討ください。

直接 Lambda リゾルバーを使用すると、 AWS Lambda データソースを使用するときに VTL マッピングテンプレートの使用を回避できます。 AWS AppSync は、Lambda 関数へのデフォルトのペイロードと、GraphQL タイプへの Lambda 関数のレスポンスからのデフォルトの変換を提供できます。リクエストテンプレート、レスポンステンプレート、またはどちらも指定できず、 AWS AppSync はそれに応じて処理します。

 AWS AppSync が提供するデフォルトのリクエストペイロードとレスポンス変換の詳細については、[「Direct Lambda リゾルバーリファレンス](resolver-mapping-template-reference-lambda.md#direct-lambda-resolvers)」を参照してください。 AWS Lambda データソースの設定と IAM 信頼ポリシーの設定の詳細については、[「データソースのアタッチ](attaching-a-data-source.md)」を参照してください。

## ダイレクト Lambda リゾルバーを設定する
<a name="direct-lambda-reference-resolvers"></a>

以下のセクションでは、Lambda データソースをアタッチし、Lambda リゾルバーをフィールドに追加する方法を示します。

### Lambda データソースを追加する
<a name="direct-lambda-datasource"></a>

ダイレクト Lambda リゾルバーをアクティブ化する前に、Lambda データソースを追加する必要があります。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[データソース]** を選択します。

1. **[データソースを作成]** を選択します。

   1. **データソース名**を使用する場合、**myFunction** のようなデータソースの名前を入力します。

   1. [**データソースタイプ**] で [**AWS Lambda 関数**] を選択します。

   1. [**リージョン**] で、該当するリージョンを選択します。

   1. **関数 ARN**を使用する場合は、ドロップダウンリストから Lambda 関数を選択します。関数名を検索するか、使用する関数の ARN を手動で入力します。

   1. 次に、新しい IAM ロールを作成するか (推奨)、`lambda:invokeFunction` への IAM アクセス許可を持つ既存のロールを選択します。[データソースのアタッチ](attaching-a-data-source.md)セクションで説明しているように、既存のロールには信頼ポリシーが必要です。

      次に、リソースで操作を実行するために必要なアクセス許可を持つ IAM ポリシーの例を示します。

------
#### [ JSON ]

****  

      ```
      { 
           "Version":"2012-10-17",		 	 	  
           "Statement": [ 
               { 
                   "Effect": "Allow", 
                   "Action": [ "lambda:invokeFunction" ], 
                   "Resource": [ 
                       "arn:aws:lambda:us-west-2:123456789012:function:myFunction", 
                       "arn:aws:lambda:us-west-2:123456789012:function:myFunction:*" 
                   ] 
               } 
           ] 
       }
      ```

------

1. **[サーバーの作成]** ボタンを選択します。

------
#### [ CLI ]

1. [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-data-source.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-data-source.html) コマンドを実行してデータソースオブジェクトを作成します。

   このコマンドには次の 4 つのパラメータを入力する必要があります。

   1. API の `api-id` です。

   1. データソースの `name`。コンソールの例では、これは**データソース名**です。

   1. データソースの `type`。コンソールの例では、これは**AWS Lambda 関数**です。

   1. コンソールの例では**関数 ARN** の `lambda-config`。
**注記**  
`Region` など、設定する必要のあるパラメータは他にもありますが、通常はデフォルトで CLI 設定値になります。

   コマンドの例は、次のようになります。

   ```
   aws appsync create-data-source --api-id abcdefghijklmnopqrstuvwxyz --name myFunction --type AWS_LAMBDA --lambda-config lambdaFunctionArn=arn:aws:lambda:us-west-2:102847592837:function:appsync-lambda-example
   ```

   出力は CLI に返されます。例を示します。

   ```
   {
       "dataSource": {
           "dataSourceArn": "arn:aws:appsync:us-west-2:102847592837:apis/abcdefghijklmnopqrstuvwxyz/datasources/myFunction",
           "type": "AWS_LAMBDA",
           "name": "myFunction",
           "lambdaConfig": {
               "lambdaFunctionArn": "arn:aws:lambda:us-west-2:102847592837:function:appsync-lambda-example"
           }
       }
   }
   ```

1. データソースの属性を変更するには、[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-data-source.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-data-source.html) コマンドを実行します。

   `api-id` パラメータを除いて、`create-data-source` コマンドで使用されているパラメータは、`update-data-source` コマンドの新しい値で上書きされます。

------

### ダイレクト Lambda リゾルバをアクティブ化する
<a name="direct-lambda-enable-templates"></a>

Lambda データソースを作成し、 AWS AppSync が関数を呼び出せるように適切な IAM ロールを設定したら、リゾルバーまたはパイプライン関数にリンクできます。

------
#### [ Console ]

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[スキーマ]** を選択します。

1. **[リゾルバー]** セクションで、フィールドまたはオペレーションを選択し、**[アタッチ]** ボタンを選択します。

1. **新しいリゾルバーを作成する**ページで、ドロップダウンリストから Lambda 関数を選択します。

1. ダイレクト Lambda リゾルバーを利用するには、リクエストとレスポンスのマッピングテンプレートが**マッピングテンプレートを設定する**セクションで無効になっていることを確認します。

1. **[リゾルバーの保存]** ボタンを選択します。

------
#### [ CLI ]
+ [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html) コマンドを実行してリゾルバーを作成します。

  このコマンドには次の 6 つのパラメータを入力する必要があります。

  1. API の `api-id`。

  1. スキーマでのタイプの `type-name`。

  1. スキーマでのフィールドの `field-name`。

  1. `data-source-name`、または Lambda 関数の名前。

  1. リクエストの本文である `request-mapping-template`。コンソールの例では、これは無効になっています。

     ```
     " "
     ```

  1. レスポンスの本文である `response-mapping-template`。コンソールの例では、これも無効になっています。

     ```
     " "
     ```

  コマンドの例は、次のようになります。

  ```
  aws appsync create-resolver --api-id abcdefghijklmnopqrstuvwxyz --type-name Subscription --field-name onCreateTodo --data-source-name LambdaTest --request-mapping-template " " --response-mapping-template " "
  ```

  出力は CLI に返されます。例を示します。

  ```
  {
      "resolver": {
          "resolverArn": "arn:aws:appsync:us-west-2:102847592837:apis/abcdefghijklmnopqrstuvwxyz/types/Subscription/resolvers/onCreateTodo",
          "typeName": "Subscription",
          "kind": "UNIT",
          "fieldName": "onCreateTodo",
          "dataSourceName": "LambdaTest"
      }
  }
  ```

------

マッピングテンプレートを無効にすると、 AWS AppSyncで発生する追加の動作がいくつかあります。
+ マッピングテンプレートを無効にすると、[Direct Lambda リゾルバーリファレンス](resolver-mapping-template-reference-lambda.md#direct-lambda-resolvers)で指定されたデフォルトのデータ変換を受け入れる AWS AppSync ことを に知らせます。
+ リクエストマッピングテンプレートを無効にすると、Lambda データソースは、[Context](resolver-context-reference.md)オブジェクト全体で構成されるペイロードを受け取ります。
+ レスポンスマッピングテンプレートを無効にすると、リクエストマッピングテンプレートのバージョン、またはリクエストマッピングテンプレートも無効になっているかどうかに応じて、Lambda 呼び出しの結果が変換されます。

# AWS AppSync (VTL) でのリゾルバーのテストとデバッグ
<a name="test-debug-resolvers"></a>

**注記**  
現在、主に APPSYNC\$1JS ランタイムとそのドキュメントをサポートしています。[こちら](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html) で APPSYNC\$1JS ランタイムとそのガイドの使用をご検討ください。

AWS AppSync は、データソースに対して GraphQL フィールドでリゾルバーを実行します。「[リゾルバーのマッピングテンプレートの概要](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview)」で説明しているように、リゾルバーはテンプレート作成言語を使用してデータソースと通信します。これにより、ユーザーは動作をカスタマイズでき、データソースと通信する前後にロジックおよび条件を適用できます。リゾルバーを記述するための入門者向けのチュートリアル形式プログラミングガイドについては、「[リゾルバーのマッピングテンプレートのプログラミングガイド](resolver-mapping-template-reference-programming-guide.md#aws-appsync-resolver-mapping-template-reference-programming-guide)」を参照してください。

デベロッパーがこれらのリゾルバーを記述、テスト、デバッグできるように、 AWS AppSync コンソールには、モックデータを含む GraphQL リクエストとレスポンスを個々のフィールドリゾルバーに作成するためのツールも用意されています。さらに、 AWS AppSync コンソールでクエリ、ミューテーション、サブスクリプションを実行し、リクエスト全体の Amazon CloudWatch からの詳細なログストリームを表示できます。ログストリームにはデータソースからの結果も含まれています。

## モックデータを使用したテスト
<a name="testing-with-mock-data"></a>

GraphQL リゾルバーが呼び出されるときに、そのリゾルバーには、リクエストに関する情報を含む `context` オブジェクトが含まれています。このオブジェクトには、クライアントからの引数、ID 情報、および親 GraphQL フィールドからのデータが含まれています。また、データソースからの結果も含まれていて、それをレスポンステンプレートで使用できます。この構造体およびプログラミング時に使用可能なヘルパーユーティリティの詳細については、「[リゾルバーのマッピングテンプレートのコンテキストリファレンス](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference)」を参照してください。

リゾルバーを記述または編集する場合に、*モック*または*テストコンテキスト*オブジェクトをコンソールエディタに渡すことができます。これにより、実際にデータソースに対して実行することなく、リクエストとレスポンスの両方のテンプレートでどのように評価されるかを確認できます。例えば、テストの `firstname: Shaggy` 引数を渡して、テンプレートのコードで `$ctx.args.firstname` を使用している場合にその引数がどのように評価されるかを確認できます。任意のユーティリティヘルパー (`$util.autoId()`、`util.time.nowISO8601()` など) での評価をテストすることもできます。

### リゾルバーのテスト
<a name="test-a-resolver"></a>

この例では、 AWS AppSync コンソールを使用してリゾルバーをテストします。

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **API ダッシュボード**で、GraphQL API を選択します。

   1. **サイドバー**で **[スキーマ]** を選択します。

1. まだ行っていない場合は、タイプの下のフィールドの横にある **[アタッチ]** を選択してリゾルバーを追加します。

   完全なリゾルバーをビルドする方法の詳細については、「[リゾルバーを設定する](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html)」を参照してください。

   それ以外の場合は、すでにフィールドにあるリゾルバーを選択してください。

1. **[リゾルバーを編集]** ページの上部で、**[テストコンテキストを選択]** を選択し、**[新しいコンテキストを作成]** を選択します。

1. サンプルコンテキストオブジェクトを選択するか、下の**実行コンテキスト**ウィンドウに JSON を手動で入力します。

1. **テキストコンテキスト名**を入力します。

1. **[保存]** ボタンを選択します。

1. **[リゾルバーを編集]** ページの上部にある **[テストを実行]** を選択します。

より現実的な例として、オブジェクトに対して自動 ID 生成を使用して Amazon DynamoDB に保存する `Dog` の GraphQL タイプを保存するアプリケーションがあるとします。また、一部の値を GraphQL ミューテーションの引数から書き込み、レスポンスが特定の 1 人のユーザーにのみ表示されるようにします。スキーマは次のようになります。

```
type Dog {
  breed: String
  color: String
}

type Mutation {
  addDog(firstname: String, age: Int): Dog
}
```

`addDog` ミューテーションに対してリゾルバーを追加するときに、次のようなコンテキストオブジェクトを入力できます。次の例には、クライアントから引数として `name` と `age` があり、`identity` オブジェクトに入力されている `username` があります。

```
{
    "arguments" : {
        "firstname": "Shaggy",
        "age": 4
    },
    "source" : {},
    "result" : {
        "breed" : "Miniature Schnauzer",
        "color" : "black_grey"
    },
    "identity": {
        "sub" : "uuid",
        "issuer" : " https://cognito-idp.{region}.amazonaws.com/{userPoolId}",
        "username" : "Nadia",
        "claims" : { },
        "sourceIp" :[  "x.x.x.x" ],
        "defaultAuthStrategy" : "ALLOW"
    }
}
```

これを、以下のリクエストとレスポンスのマッピングテンプレートを使用してテストします。

 **リクエストテンプレート** 

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "id" : { "S" : "$util.autoId()" }
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
```

 **レスポンステンプレート** 

```
#if ($context.identity.username == "Nadia")
  $util.toJson($ctx.result)
#else
  $util.unauthorized()
#end
```

評価後のテンプレートには、テストコンテキストオブジェクトからのデータと、`$util.autoId()` から生成された値があります。また、`username` を `Nadia` 以外の値に変更した場合は、認可チェックが失敗するため、結果は返されません。きめ細かなアクセス制御の詳細については、「[認可のユースケース](security-authorization-use-cases.md#aws-appsync-security-authorization-use-cases)」を参照してください。

### AWS AppSync の APIs を使用したマッピングテンプレートのテスト
<a name="testing-with-appsync-api"></a>

`EvaluateMappingTemplate` API コマンドを使用して、モックデータを使用してマッピングテンプレートをリモートでテストできます。コマンドを使い始めるには、ポリシーに `appsync:evaluateMappingTemplate` アクセス許可を追加していることを確認してください。例えば、次のようになります。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appsync:evaluateMappingTemplate",
            "Resource": "arn:aws:appsync:us-east-1:111122223333:*"
        }
    ]
}
```

------

[AWS CLI](https://aws.amazon.com/cli/) または [AWS SDK](https://aws.amazon.com/tools/) を使用してコマンドを活用できます。例えば、前のセクションから、`Dog` スキーマとそのリクエスト/レスポンスマッピングテンプレートを見てみましょう。ローカルステーションの CLI を使用して、リクエストテンプレートを `request.vtl` という名前のファイルに保存し、`context` オブジェクトを `context.json` という名前のファイルに保存します。シェルから次のコマンドを実行します。

```
aws appsync evaluate-mapping-template --template file://request.vtl --context file://context.json
```

このコマンドは、次のレスポンスを返します。

```
{
  "evaluationResult": "{\n    \"version\" : \"2017-02-28\",\n    \"operation\" : \"PutItem\",\n    \"key\" : {\n        \"id\" : { \"S\" : \"afcb4c85-49f8-40de-8f2b-248949176456\" }\n    },\n    \"attributeValues\" : {\"firstname\":{\"S\":\"Shaggy\"},\"age\":{\"N\":4}}\n}\n"
}
```

`evaluationResult` には、提供されたテンプレートを提供された `context` とともにテストした結果が含まれています。 AWS SDKs を使用してテンプレートをテストすることもできます。 AWS SDK for JavaScript V2 を使用した例を次に示します。

```
const AWS = require('aws-sdk')
const client = new AWS.AppSync({ region: 'us-east-2' })

const template = fs.readFileSync('./request.vtl', 'utf8')
const context = fs.readFileSync('./context.json', 'utf8')

client
  .evaluateMappingTemplate({ template, context })
  .promise()
  .then((data) => console.log(data))
```

SDK を使用すると、お気に入りのテストスイートのテストを簡単に組み込んで、テンプレートの動作を検証できます。[Jest テストフレームワーク](https://jestjs.io/)を使用してテストを作成することをお勧めしますが、どのテストスイートでも問題ありません。次のスニペットは、仮説検証の実行を示しています。評価レスポンスは有効な JSON であることを想定しているので、`JSON.parse`を使用して文字列レスポンスから JSON を取得することに注意してください。

```
const AWS = require('aws-sdk')
const fs = require('fs')
const client = new AWS.AppSync({ region: 'us-east-2' })

test('request correctly calls DynamoDB', async () => {
  const template = fs.readFileSync('./request.vtl', 'utf8')
  const context = fs.readFileSync('./context.json', 'utf8')
  const contextJSON = JSON.parse(context)
  
  const response = await client.evaluateMappingTemplate({ template, context }).promise()
  const result = JSON.parse(response.evaluationResult)
  
  expect(result.key.id.S).toBeDefined()
  expect(result.attributeValues.firstname.S).toEqual(contextJSON.arguments.firstname)
})
```

 これにより、次のような結果が得られます。

```
Ran all test suites.
> jest

PASS ./index.test.js
✓ request correctly calls DynamoDB (543 ms)

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.511 s, estimated 2 s
```

## ライブクエリのデバッグ
<a name="debugging-a-live-query"></a>

本番アプリケーションをデバッグするためのend-to-endのテストとログ記録に代わるものはありません。 AWS AppSync では、Amazon CloudWatch を使用してエラーとリクエストの詳細全体をログ記録できます。さらに、 AWS AppSync コンソールを使用して、各リクエストの GraphQL クエリ、ミューテーション、サブスクリプション、ライブストリームログデータをテストし、クエリエディタに戻し、リアルタイムでデバッグできます。サブスクリプションに関して表示されるログは接続時の情報です。

これを実行するには、「[モニタリングとロギング](monitoring.md#aws-appsync-monitoring)」で説明しているように、Amazon CloudWatch Logs を事前に有効にしておく必要があります。次に、 AWS AppSync コンソールで**クエリ**タブを選択し、有効な GraphQL クエリを入力します。右下のセクションで、**[ログ]** ウィンドウをクリックしてドラッグし、ログビューを開きます。ページの上部にある再生矢印アイコンを選択して GraphQL クエリを実行します。しばらくすると、そのオペレーションのリクエストとレスポンスの完全なログが、このセクションにストリーミングされ、コンソールで表示できます。

# AWS AppSync (VTL) でのパイプラインリゾルバーの設定と使用
<a name="pipeline-resolvers"></a>

**注記**  
現在、主に APPSYNC\$1JS ランタイムとそのドキュメントをサポートしています。[こちら](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html) で APPSYNC\$1JS ランタイムとそのガイドの使用をご検討ください。

AWS AppSync は GraphQL フィールドでリゾルバーを実行します。場合によっては、アプリケーションは 1 つの GraphQL フィールドを解決するために複数のオペレーションを実行する必要があります。パイプラインリゾルバーを使用すると、開発者は関数と呼ばれるオペレーションを構成して順番に実行できます。パイプラインリゾルバーは、たとえば、フィールドのデータを取得する前に承認チェックを実行する必要があるアプリケーションに便利です。

パイプラインリゾルバーは、**Before** マッピングテンプレート、**After** マッピングテンプレート、関数のリストで構成されています。各関数には、データソースに対して実行される**リクエスト**および**レスポンス**マッピングテンプレートがあります。パイプラインリゾルバーは実行をリスト内の関数に委任するため、いずれのデータソースにもリンクされていません。ユニットリゾルバーと関数は、データソースに対してオペレーションを実行するプリミティブです。詳細については、「[リゾルバーのマッピングテンプレートの概要](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview)」を参照してください。

## ステップ 1: パイプラインリゾルバーを作成する
<a name="create-a-pipeline-resolver"></a>

 AWS AppSync コンソールで、**スキーマ**ページに移動します。

以下のスキーマを保存します。

```
schema {
    query: Query
    mutation: Mutation
}

type Mutation {
    signUp(input: Signup): User
}

type Query {
    getUser(id: ID!): User
}

input Signup {
    username: String!
    email: String!
}

type User {
    id: ID!
    username: String
    email: AWSEmail
}
```

パイプラインリゾルバーを**ミューテーション**タイプの **SignUp** フィールドに書き込みます。右側の **[ミューテーション]** タイプに入力し、[`signUp` ミューテーション] フィールドの横の **[アタッチ]** を選択します。[リゾルバーの作成] ページで、**[アクション]**、**[ランタイム更新]** の順にクリックします。[`Pipeline Resolver`]、[`VTL`] の順に選択してから、**[更新]** を選択します。このページには、**Before マッピングテンプレート**テキスト領域、**関数**セクション、**After マッピングテンプレート**テキスト領域の 3 つのセクションが表示されています。

パイプラインリゾルバーは、最初に E メールアドレスの入力を検証してからシステムにユーザーを保存することで、ユーザーをサインアップします。E メールの検証を **validateEmail** 関数内にカプセル化し、ユーザーの保存を **saveUser** 関数内にカプセル化します。**validateEmail** 関数が最初に実行され、E メールが有効であれば、**saveUser** 関数が実行されます。

実行フローは以下のようになります。

1. Mutation.signUp リゾルバーのリクエストマッピングテンプレート

1. validateEmail 関数

1. saveUser 関数

1. Mutation.signUp リゾルバーのレスポンスマッピングテンプレート

API の他のリゾルバーで **validateEmail** 関数を再利用することが多いため、GraphQL フィールド間でアクセス先の `$ctx.args` が変わるのを避けるとします。この場合、代わりに `$ctx.stash` を使用して、`signUp(input: Signup)` 入力フィールド引数からの email 属性を保存できます。

**BEFORE** マッピングテンプレート:

```
## store email input field into a generic email key
$util.qr($ctx.stash.put("email", $ctx.args.input.email))
{}
```

コンソールから、デフォルトのパススルー **AFTER** マッピングテンプレートを使用できます。

```
$util.toJson($ctx.result)
```

**[作成]** または **[保存]** を選択してリゾルバーを更新します。

## ステップ 2: 関数を作成する
<a name="create-a-function"></a>

パイプラインリゾルバーページの **[関数]** セクションで、**[関数の作成]** をクリックして、**[新しい関数の作成]** をクリックします。リゾルバーページを経由せずに関数を作成することもできます。これを行うには、 AWS AppSync コンソールで**関数**ページに移動します。**[関数の作成]** ボタンを選択します。E メールが有効であり特定のドメインからのものかどうかをチェックする関数を作成しましょう。E メールが無効な場合、この関数はエラーを発生させます。それ以外の場合、渡された入力をすべて転送します。

新しい関数ページで、**[アクション]** を選択して、**[ランタイムを更新]** を選択します。[`VTL`] を選択してから、**[更新]** を選択します。**NONE** 型のデータソースが作成されたことを確認してください。**[データソース名]** リストでこのデータソースを選択します。**[関数名]** に `validateEmail` と入力します。**関数コード** 領域で、次のスニペットですべてを上書きします。

```
#set($valid = $util.matches("^[a-zA-Z0-9_.+-]+@(?:(?:[a-zA-Z0-9-]+\.)?[a-zA-Z]+\.)?(myvaliddomain)\.com", $ctx.stash.email))
#if (!$valid)
    $util.error("$ctx.stash.email is not a valid email.")
#end
{
    "payload": { "email": $util.toJson(${ctx.stash.email}) }
}
```

レスポンスマッピングテンプレートにこれを貼り付けます。

```
$util.toJson($ctx.result)
```

変更内容を確認し、**[作成]** を選択します。これで、**validateEmail** 関数が作成されました。次のリクエストマッピングテンプレートとレスポンスマッピングテンプレートでこれらの手順を繰り返し、**saveUser** 関数を作成します (わかりやすくするため、**NONE** データソースを使用し、関数が実行された後にユーザーがシステムに保存されたものとしています。): 

リクエストマッピングテンプレート:

```
## $ctx.prev.result contains the signup input values. We could have also
## used $ctx.args.input.
{
    "payload": $util.toJson($ctx.prev.result)
}
```

レスポンスマッピングテンプレート

```
## an id is required so let's add a unique random identifier to the output
$util.qr($ctx.result.put("id", $util.autoId()))
$util.toJson($ctx.result)
```

これで、**saveUser** 関数が作成されました。

## ステップ 3: パイプラインリゾルバーに関数を追加する
<a name="adding-a-function-to-a-pipeline-resolver"></a>

先ほど作成したパイプラインリゾルバーには関数が自動的に追加されています。そうでない場合、または **[関数]** ページで関数を作成した場合は、リゾルバーページの **[関数を追加]** をクリックして、それらの関数をアタッチできます。**validateEmail** と **saveUser** の両方の関数をリゾルバーに追加します。**validateEmail** 関数は **saveUser** 関数の前に配置する必要があります。関数を追加するときには、**上に移動**および**下に移動**オプションを使用して関数の実行順序を並べ替えることができます。変更を確認し、**[保存]** を選択します。

## ステップ 4: クエリを実行する
<a name="executing-a-query"></a>

 AWS AppSync コンソールで、**クエリ**ページに移動します。Explorer で、ミューテーションを使用していることを確認します。そうでない場合は、ドロップダウンリストから [`Mutation`] を選択し、[`+`] を選択します。以下のクエリを入力します。

```
mutation {
  signUp(input: {
    email: "nadia@myvaliddomain.com"
    username: "nadia"
  }) {
    id
    email
  }
}
```

以下のように返されます。

```
{
  "data": {
    "signUp": {
      "id": "256b6cc2-4694-46f4-a55e-8cb14cc5d7fc",
      "email": "nadia@myvaliddomain.com"
    }
  }
}
```

これで、パイプラインリゾルバーを使用して、ユーザーをサインアップし、入力 E メールを検証できました。パイプラインリゾルバーに焦点を当てたより完全なチュートリアルについては、「[チュートリアル: パイプラインリゾルバー](tutorial-pipeline-resolvers.md#aws-appsync-tutorial-pipeline-resolvers)」を参照してください。

# AWS CDK での AWS AppSync API の使用
<a name="using-your-api"></a>

**ヒント**  
CDK を使用する前に、CDK の[公式ドキュメント](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html)と CDK AWS AppSyncリファレンスを確認することをお勧めします。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
また、[AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) と [NPM](https://docs.npmjs.com/) のインストールがシステム上で動作していることを確認することをお勧めします。

このセクションでは、DynamoDB テーブルに項目を追加したり、テーブルから項目を取得したりできる簡単な CDK アプリケーションを作成します。これは、[[スキーマの設計]](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html)、[[データソースのアタッチ]](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)、[[リゾルバーの設定 (JavaScript)]](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html) セクションのコードの一部を使用したクイックスタートの例です。

## CDK プロジェクトのセットアップ
<a name="Setting-up-a-cdk-project"></a>

**警告**  
環境によっては、これらの手順が完全に正確ではない場合があります。システムに必要なユーティリティがインストールされていること、 AWS サービスとインターフェイスする方法、および適切な設定が整っていることを前提としています。

最初のステップは AWS CDK のインストールです。CLI で、次のコマンドを入力できます。

```
npm install -g aws-cdk
```

次に、プロジェクトディレクトリを作成して、そこに移動する必要があります。ディレクトリを作成して、そこに移動するコマンドのセット例は次のとおりです。

```
mkdir example-cdk-app
cd example-cdk-app
```

次に、アプリを作成する必要があります。私たちのサービスは主に TypeScript を使用しています。プロジェクトディレクトリで次のコマンドを入力します。

```
cdk init app --language typescript
```

これを行うと、CDK アプリとその初期化ファイルがインストールされます。

![\[Terminal output showing Git repository initialization and npm install completion.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-init-app-example.png)


プロジェクト構造は次のようになります。

![\[Project directory structure showing folders and files for an example CDK app.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-init-directories.png)


いくつかの重要なディレクトリがあるのがわかります。
+ `bin`: 最初の bin ファイルによってアプリが作成されます。このガイドではこれについては触れません。
+ `lib`: lib ディレクトリにはスタックファイルが含まれます。スタックファイルは個々の実行単位と考えることができます。コンストラクトはスタックファイル内にあります。基本的に、これらはアプリケーションのデプロイ CloudFormation 時に でスピンアップされるサービスのリソースです。ほとんどのコーディングはここで行われます。
+ `node_modules`: このディレクトリは NPM によって作成され、`npm` コマンドを使用してインストールしたすべてのパッケージ依存関係が含まれます。

最初のスタックファイルには次のような内容が含まれる場合があります。

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    // example resource
    // const queue = new sqs.Queue(this, 'ExampleCdkAppQueue', {
    //   visibilityTimeout: cdk.Duration.seconds(300)
    // });
  }
}
```

これはアプリでスタックを作成するためのボイラープレートコードです。この例では、コードのほとんどはこのクラスのスコープ内にあります。

スタックファイルがアプリ内にあることを確認し、アプリのディレクトリからターミナルで以下のコマンドを実行します。

```
cdk ls
```

スタックが一覧表示されます。表示されない場合は、手順をもう一度実行するか、公式ドキュメントでヘルプを確認する必要があります。

デプロイする前にコードの変更をビルドする場合は、ターミナルでいつでも以下のコマンドを実行できます。

```
npm run build
```

また、デプロイ前に変更を確認します。

```
cdk diff
```

スタックファイルにコードを追加する前に、ブートストラップを実行します。ブートストラップにより、アプリがデプロイされる前に CDK にリソースをプロビジョニングできます。このプロセスの詳細については、[こちら](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html)を参照してください。ブートストラップを作成するには、以下のコマンドを実行します。

```
cdk bootstrap aws://ACCOUNT-NUMBER/REGION
```

**ヒント**  
このステップでは、アカウントに複数の IAM アクセス許可が必要です。これらのアクセス許可がないと、ブートストラップは拒否されます。拒否された場合、ブートストラップが生成する S3 バケットなど、ブートストラップが原因で発生した不完全なリソースを削除しなければならない場合があります。

ブートストラップは複数のリソースを起動します。最終メッセージは次のようになります。

![\[Terminal output showing successful bootstrapping of an AWS environment.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-init-bootstrap-final.png)


これは各リージョンのアカウントごとに 1 回行われるため、頻繁に行う必要はありません。ブートストラップの主なリソースは、 CloudFormation スタックと Amazon S3 バケットです。

Amazon S3 バケットは、ファイルとデプロイの実行に必要なアクセス許可を付与する IAM ロールを保存するために使用されます。必要なリソースは、ブートストラップ CloudFormation スタックと呼ばれる スタックで定義され、通常は と呼ばれます`CDKToolkit`。他の CloudFormation スタックと同様に、デプロイされると CloudFormation コンソールに表示されます。

![\[CDKToolkit stack with CREATE_COMPLETE status in CloudFormation console.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-init-bootstrap-cfn-console.png)


バケットについても同じことが言えます。

![\[S3 bucket details showing name, region, access settings, and creation date.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-init-bootstrap-bucket-console.png)


スタックファイルで必要なサービスをインポートするには、以下のコマンドを使用できます。

```
npm install aws-cdk-lib # V2 command
```

**ヒント**  
V2 に問題がある場合は、V1 コマンドを使用して個々のライブラリをインストールできます。  

```
npm install @aws-cdk/aws-appsync @aws-cdk/aws-dynamodb
```
V1 は廃止されたため、これはお勧めしません。

## CDK プロジェクトを作成する - スキーマ
<a name="implementing-a-cdk-project-schema"></a>

これで、コードの実装を開始できます。まず、スキーマを作成する必要があります。アプリ内で `.graphql` ファイルを作成するだけです。

```
mkdir schema
touch schema.graphql
```

この例では、`schema.graphql` を含む `schema` という最上位ディレクトリを含めました。

![\[File structure showing a schema folder containing schema.graphql file.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-schema-directory.png)


スキーマの中に、簡単な例を含めてみましょう。

```
input CreatePostInput {
    title: String
    content: String
}

type Post {
    id: ID!
    title: String
    content: String
}

type Mutation {
    createPost(input: CreatePostInput!): Post
}

type Query {
    getPost: [Post]
}
```

スタックファイルに戻って、次の import ディレクティブが定義されていることを確認する必要があります。

```
import * as cdk from 'aws-cdk-lib';
import * as appsync from 'aws-cdk-lib/aws-appsync';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
```

クラス内に、GraphQL API を作成して `schema.graphql` ファイルに接続するコードを追加します。

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    // makes a GraphQL API
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });
  }
}
```

また、GraphQL URL、API キー、リージョンを出力するコードもいくつか追加します。

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

この時点で、アプリを再度デプロイします。

```
cdk deploy
```

こちらがその結果です。

![\[Deployment output showing ExampleCdkAppStack details, including GraphQL API URL and stack region.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-schema.png)


この例は成功したようですが、 AWS AppSync コンソールを確認して確認しましょう。

![\[GraphQL interface showing successful API request with response data displayed.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-schema-result-1.png)


API が作成されたようです。次に、API に添付されているスキーマを確認します。

![\[GraphQL schema defining CreatePostInput, Post type, Mutation, and Query operations.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-schema-result-2.png)


これはスキーマコードと一致しているようなので、成功です。メタデータの観点からこれを確認するもう 1 つの方法は、 CloudFormation スタックを確認することです。

![\[CloudFormation stack showing ExampleCdkAppStack update complete and CDKToolkit creation complete.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-schema-result-3.png)


CDK アプリケーションをデプロイすると、ブートストラップなどのリソース CloudFormation がスピンアップされます。アプリ内の各スタックは、 CloudFormation スタックと 1:1 でマッピングされます。スタックコードに戻ると、スタック名はクラス名 `ExampleCdkAppStack` から取得されています。作成したリソースを確認でき、GraphQL API コンストラクトの命名規則とも一致しています。

![\[Expanded view of post-apis resource showing Schema, DefaultApiKey, and CDKMetadata.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-schema-result-4.png)


## CDK プロジェクトの実装 - データソース
<a name="implementing-a-cdk-project-data-source"></a>

次に、データソースを追加する必要があります。この例では DynamoDB テーブルを使用します。stack クラス内に、新しいテーブルを作成するコードをいくつか追加します。

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    //creates a DDB table
    const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
      partitionKey: {
        name: 'id',
        type: dynamodb.AttributeType.STRING,
      },
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

この時点で、もう一度デプロイしてみましょう。

```
cdk deploy
```

DynamoDB コンソールで新しいテーブルを確認する必要があります。

![\[DynamoDB console showing ExampleCdkAppStack-poststable as Active with Provisioned capacity.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-ddb-result-1.png)


スタック名は正しく、テーブル名はコードと一致しています。 CloudFormation スタックを再度チェックすると、新しいテーブルが表示されます。

![\[Expanded view of a logical ID in CloudFormation showing post-apis, posts-table, and CDKMetadata.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-ddb-result-2.png)


## CDK プロジェクトを作成する - リゾルバー
<a name="implementing-a-cdk-project-resolver"></a>

この例では、2 つのリゾルバーを使用します。1 つはテーブルのクエリ用、もう 1 つはテーブルへの追加用です。パイプラインリゾルバーを使用しているため、それぞれ 1 つの関数を持つ 2 つのパイプラインリゾルバーを宣言する必要があります。このクエリでは、次のコードを追加します。

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    //creates a DDB table
    const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
      partitionKey: {
        name: 'id',
        type: dynamodb.AttributeType.STRING,
      },
    });

    // Creates a function for query
    const add_func = new appsync.AppsyncFunction(this, 'func-get-post', {
      name: 'get_posts_func_1',
      api,
      dataSource: api.addDynamoDbDataSource('table-for-posts', add_ddb_table),
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return { operation: 'Scan' };
          }

          export function response(ctx) {
          return ctx.result.items;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
    });

    // Creates a function for mutation
    const add_func_2 = new appsync.AppsyncFunction(this, 'func-add-post', {
      name: 'add_posts_func_1',
      api,
      dataSource: api.addDynamoDbDataSource('table-for-posts-2', add_ddb_table),
      code: appsync.Code.fromInline(`
          export function request(ctx) {
            return {
            operation: 'PutItem',
            key: util.dynamodb.toMapValues({id: util.autoId()}),
            attributeValues: util.dynamodb.toMapValues(ctx.args.input),
            };
          }

          export function response(ctx) {
            return ctx.result;
          }
      `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
    });

    // Adds a pipeline resolver with the get function
    new appsync.Resolver(this, 'pipeline-resolver-get-posts', {
      api,
      typeName: 'Query',
      fieldName: 'getPost',
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return {};
          }

          export function response(ctx) {
          return ctx.prev.result;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
      pipelineConfig: [add_func],
    });

    // Adds a pipeline resolver with the create function
    new appsync.Resolver(this, 'pipeline-resolver-create-posts', {
      api,
      typeName: 'Mutation',
      fieldName: 'createPost',
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return {};
          }

          export function response(ctx) {
          return ctx.prev.result;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
      pipelineConfig: [add_func_2],
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

このスニペットでは、`func-add-post` という関数がアタッチされた `pipeline-resolver-create-posts` というパイプラインリゾルバーを追加しました。これがテーブルに `Posts` を追加するコードです。もう一方のパイプラインリゾルバーは `pipeline-resolver-get-posts` と呼ばれ、テーブルに追加された `Posts` を取得する `func-get-post` と呼ばれる関数を持ちます。

これをデプロイして AWS AppSync サービスに追加します。

```
cdk deploy
```

 AWS AppSync コンソールをチェックして、それらが GraphQL API にアタッチされているかどうかを確認します。

![\[GraphQL API schema showing mutation and query fields with Pipeline resolvers.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-1.png)


正しく接続されているようです。コードでは、これらのリゾルバーは両方とも、作成した GraphQL API にアタッチされていました (リゾルバーと関数の両方に存在する `api` props 値で示されます)。GraphQL APIでは、リゾルバーをアタッチしたフィールドも props で指定されていました (各リゾルバーで `typename` および `fieldname` props によって定義されます)。

リゾルバーのコンテンツが正しいかどうか、`pipeline-resolver-get-posts` を手始めに見てみましょう。

![\[Code snippet showing request and response functions in a resolver, with an arrow pointing to them.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-2.png)


before ハンドラーと after ハンドラーは `code` props の値と一致しています。また、`add_posts_func_1` という関数がリゾルバーにアタッチした関数の名前と一致していることもわかります。

この関数のコードコンテンツを見てみましょう。

![\[Function code showing request and response methods for a PutItem operation.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-3.png)


これは `add_posts_func_1` 関数の `code` props と一致します。クエリが正常にアップロードされたので、クエリを確認してみましょう。

![\[Resolver code with request and response functions, and a get_posts_func_1 function listed below.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-4.png)


これらもコードと一致しています。`get_posts_func_1` を見てみましょう。

![\[Code snippet showing two exported functions: request returning 'Scan' operation and response returning items.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-5.png)


すべてが正常に見えます。メタデータの観点からこれを確認するには、スタックをもう一度 CloudFormation にチェックインします。

![\[List of logical IDs for AWS resources including API, table, functions, and pipelines.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-6.png)


次に、いくつかのリクエストを実行して、このコードをテストする必要があります。

## CDK プロジェクトの実装 - リクエスト
<a name="implementing-a-cdk-project-requests"></a>

 AWS AppSync コンソールでアプリケーションをテストするために、1 つのクエリと 1 つのミューテーションを作成しました。

![\[GraphQL code snippet showing a query to get post details and a mutation to create a post.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-request-1.png)


`MyMutation` には、引数 `1970-01-01T12:30:00.000Z` と `first post` を含む `createPost` オペレーションが含まれています。渡した `date` および `title` とともに、自動生成された `id` 値が返されます。ミューテーションを実行すると、以下の結果が得られます。

```
{
  "data": {
    "createPost": {
      "date": "1970-01-01T12:30:00.000Z",
      "id": "4dc1c2dd-0aa3-4055-9eca-7c140062ada2",
      "title": "first post"
    }
  }
}
```

DynamoDB テーブルをすばやく確認すると、スキャンしたときにテーブルにエントリが表示されます。

![\[DynamoDB table entry showing id, date, and title fields for a single item.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cdk-code-request-2.png)


 AWS AppSync コンソールに戻り、クエリを実行してこの を取得すると`Post`、次の結果が得られます。

```
{
  "data": {
    "getPost": [
      {
        "id": "9f62c4dd-49d5-48d5-b835-143284c72fe0",
        "date": "1970-01-01T12:30:00.000Z",
        "title": "first post"
      }
    ]
  }
}
```

# でのリアルタイムデータアプリケーションのサブスクリプションの使用 AWS AppSync
<a name="aws-appsync-real-time-data"></a>

**重要**  
2025 年 3 月 13 日以降、 AWS AppSync Events を使用して WebSockets を搭載したリアルタイム PubSub API を構築できます。詳細については、「*AWS AppSync Events デベロッパーガイド*」の「[WebSocket 経由でイベントを公開する](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html)」を参照してください。

AWS AppSync では、サブスクリプションを利用して、ライブアプリケーションの更新、プッシュ通知などを実装できます。クライアントが GraphQL サブスクリプションオペレーションを呼び出すと、 AWS AppSync によって安全な WebSocket 接続が自動的に確立され、維持されます。その後、アプリケーションはデータソースからサブスクライバーにデータをリアルタイムで配信でき、 AWS AppSync はアプリケーションの接続とスケーリング要件を継続的に管理します。以下のセクションでは、 AWS AppSync のサブスクリプションの仕組みを示します。

## GraphQL スキーマサブスクリプションディレクティブ
<a name="graphql-schema-subscription-directives"></a>

 AWS AppSync のサブスクリプションは、ミューテーションへの応答として呼び出されます。つまり、ミューテーションに GraphQL スキーマディレクティブを指定することで、 AWS AppSync のデータソースをリアルタイムで作成できます。

 AWS Amplify クライアントライブラリは、サブスクリプション接続管理を自動的に処理します。ライブラリは純粋な WebSockets をクライアントとサービス間のネットワークプロトコルとして使用します。

**注記**  
サブスクリプションへの接続時に認可を制御するには、 AWS Identity and Access Management (IAM) AWS Lambda、、Amazon Cognito ID プール、または Amazon Cognito ユーザープールを使用して、フィールドレベルの認可を行うことができます。サブスクリプションのきめ細かなアクセスコントロールの場合、リゾルバーをサブスクリプションフィールドにアタッチし、発信者と AWS AppSync データソースの ID を使用してロジックを実行できます。詳細については、「[GraphQL API を保護するための認可と認証の設定](security-authz.md)」を参照してください。

サブスクリプションはミューテーションからトリガーされ、ミューテーション選択セットが受信者に送信されます。

次の例では、GraphQL サブスクリプションの操作方法を示します。データソースを指定しません。これは、データソースが 、Amazon DynamoDB、または Amazon OpenSearch Service のいずれかであるからです。

サブスクリプションを開始するには、次のようにスキーマにサブスクリプションのエントリポイントを追加します。

```
schema {
    query: Query
    mutation: Mutation
    subscription: Subscription
}
```

ブログ投稿サイトを持っており、新しいブログにサブスクライブし、既存のブログに変わるものとします。これを行うには、スキーマに次の `Subscription` 定義を追加します。

```
type Subscription {
    addedPost: Post
    updatedPost: Post
    deletedPost: Post
}
```

さらに、次のミューテーションがあるとします。

```
type Mutation {
    addPost(id: ID! author: String! title: String content: String url: String): Post!
    updatePost(id: ID! author: String! title: String content: String url: String ups: Int! downs: Int! expectedVersion: Int!): Post!
    deletePost(id: ID!): Post!
}
```

通知を受け取る各サブスクリプションに `@aws_subscribe(mutations: ["mutation_field_1", "mutation_field_2"])` ディレクティブを追加することで、これらのフィールドをリアルタイム対応にできます。手順は以下のとおりです。

```
type Subscription {
    addedPost: Post
    @aws_subscribe(mutations: ["addPost"])
    updatedPost: Post
    @aws_subscribe(mutations: ["updatePost"])
    deletedPost: Post
    @aws_subscribe(mutations: ["deletePost"])
}
```

`@aws_subscribe(mutations: ["",..,""])` は、ミューテーション入力の配列を受け取るため、サブスクリプションを開始する複数のミューテーションを指定できます。クライアントからサブスクライブする場合、GraphQL クエリは次のようになります。

```
subscription NewPostSub {
    addedPost {
        __typename
        version
        title
        content
        author
        url
    }
}
```

このサブスクリプションクエリは、クライアント接続とツールに必要です。

ピュアな WebSocket クライアントを使用する場合、各クライアントが独自の選択セットを定義できるため、選択セットのフィルタリングはクライアントごとに行われます。この場合、サブスクリプション選択セットは、ミューテーション選択セットのサブセットである必要があります。例えば、サブスクリプションが `addedPost{author title}` ミューテーションにリンクされていると、`addPost(...){id author title url version}` 投稿の作成者とタイトルのみを受け取ります。他のフィールドは受け取りません。ただし、ミューテーションの選択セットに作成者が欠けていた場合、サブスクライバーは作成者フィールドに対して `null` 値を取得します (または、スキーマ内で作成者フィールドが required/not-null と定義されている場合はエラー)。

ピュアな WebSockets を使用する場合は、サブスクリプション選択セットが不可欠です。サブスクリプションでフィールドが明示的に定義されていない場合、 AWS AppSync は フィールドを返しません。

前の例では、サブスクリプションに引数はありませんでした。次のようなスキーマがあるとします。

```
type Subscription {
    updatedPost(id:ID! author:String): Post
    @aws_subscribe(mutations: ["updatePost"])
}
```

この場合、クライアントでサブスクリプションが次のように定義されます。

```
subscription UpdatedPostSub {
    updatedPost(id:"XYZ", author:"ABC") {
        title
        content
    }
}
```

スキーマの `subscription` フィールドの戻り値の型は、対応する mutation フィールドの戻り値の型に一致する必要があります。前の例では、これが `addPost` と `addedPost` の両方が `Post` タイプとして返され、表示されます。

クライアントでサブスクリプションをセットアップするには、「[Amplify クライアントを使用したクライアントアプリケーションの構築](building-a-client-app.md)」を参照してください。

## サブスクリプション引数の使用
<a name="using-subscription-arguments"></a>

GraphQL サブスクリプションを使用する上で重要なのは、引数をいつ、どのように使うかを理解することです。微妙な変更を加えることで、発生したミューテーションをクライアントに通知する方法とタイミングを変更できます。そのためには、クイックスタートの章にある「Todos」を作成するサンプルスキーマを参照してください。このサンプルスキーマでは、以下のミューテーションが定義されます。

```
type Mutation {
    createTodo(input: CreateTodoInput!): Todo
    updateTodo(input: UpdateTodoInput!): Todo
    deleteTodo(input: DeleteTodoInput!): Todo
}
```

デフォルトのサンプルでは、クライアントは引数なしで `onUpdateTodo` `subscription` を使うことで、任意の `Todo` への更新を購読できます。

```
subscription OnUpdateTodo {
  onUpdateTodo {
    description
    id
    name
    when
  }
}
```

引数を使用して `subscription` をフィルタリングできます。例えば、特定の `ID` を含む `todo` が更新された場合に `subscription` のみをトリガーするには、`ID` 値を指定します。

```
subscription OnUpdateTodo {
  onUpdateTodo(id: "a-todo-id") {
    description
    id
    name
    when
  }
}
```

複数の引数を渡すこともできます。例えば、次の `subscription` は、特定の場所と時間に `Todo` 更新があった場合に通知を受ける方法を示しています。

```
subscription todosAtHome {
  onUpdateTodo(when: "tomorrow", where: "at home") {
    description
    id
    name
    when
    where
  }
}
```

引数はすべてオプションであることに注意してください。`subscription` で引数を指定しない場合、アプリケーションで発生するすべての `Todo` 更新を購読することになります。ただし、`subscription` のフィールド定義を更新して `ID` 引数を必須にすることはできます。これにより、すべての `todo` の代わりに、特定の `todo` への応答が強制されます。

```
onUpdateTodo(
  id: ID!,
  name: String,
  when: String,
  where: String,
  description: String
): Todo
```

### 引数値 null には意味があります。
<a name="argument-null-value-has-meaning"></a>

 AWS AppSync でサブスクリプションクエリを作成する場合、`null`引数の値は引数を完全に省略するのとは異なる方法で結果をフィルタリングします。

todo を作成できる todos API サンプルに戻りましょう。クイックスタートの章にあるサンプルスキーマを参照してください。

スキーマを変更して、所有者が誰であるかを記述する新しい `owner` フィールドを `Todo` タイプに追加してみましょう。`owner` フィールドは必須ではなく、`UpdateTodoInput` に設定することしかできません。スキーマの次の簡略版を参照してください。

```
type Todo {
  id: ID!
  name: String!
  when: String!
  where: String!
  description: String!
  owner: String
}

input CreateTodoInput {
  name: String!
  when: String!
  where: String!
  description: String!
}

input UpdateTodoInput {
  id: ID!
  name: String
  when: String
  where: String
  description: String
  owner: String
}

type Subscription {
    onUpdateTodo(
        id: ID,
        name: String,
        when: String,
        where: String,
        description: String
    ): Todo @aws_subscribe(mutations: ["updateTodo"])
}
```

次のサブスクリプションはすべての `Todo` 更新を返します。

```
subscription MySubscription {
  onUpdateTodo {
    description
    id
    name
    when
    where
  }
}
```

前のサブスクリプションを変更してフィールド引数 `owner: null` を追加すると、別の質問をすることになります。これで、所有者が指定されていないすべての `Todo` 更新について通知を受けることができるように、このサブスクリプションによってクライアントが登録されるようになりました。

```
subscription MySubscription {
  onUpdateTodo(owner: null) {
    description
    id
    name
    when
    where
  }
}
```

**注記**  
**2022 年 1 月 1 日現在、MQTT over WebSockets は API の GraphQL サブスクリプションのプロトコルとして利用できなくなりました。 AWS AppSync APIs Pure WebSockets は、 でサポートされている唯一のプロトコルです AWS AppSync。**  
2019 年 11 月以降にリリースされた AWS AppSync SDK または Amplify ライブラリに基づくクライアントは、デフォルトで純粋な WebSocketsを自動的に使用します。クライアントを最新バージョンにアップグレードすると、 AWS AppSyncクライアントは純粋な WebSockets エンジンを使用できます。  
純粋な WebSockets には、より大きなペイロードサイズ (240KB)、幅広いクライアントオプション、改善された CloudWatch メトリックスが付属しています。純粋な WebSocket クライアントを使用する方法の詳細については、「[ AWS AppSync でのリアルタイム WebSocket クライアントの構築](real-time-websocket-client.md)」を参照してください。

# でのサーバーレス WebSockets を使用した汎用 pub/sub APIs の作成 AWS AppSync
<a name="aws-appsync-real-time-create-generic-api-serverless-websocket"></a>

**重要**  
2025 年 3 月 13 日以降、 AWS AppSync Events を使用して WebSockets を搭載したリアルタイム PubSub API を構築できます。詳細については、「*AWS AppSync Events デベロッパーガイド*」の「[WebSocket 経由でイベントを公開する](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html)」を参照してください。

一部のアプリケーションでは、クライアントが特定のチャネルまたはトピックをリスンする単純な WebSocket API のみが必要です。特定の形式や厳密に型指定された要件のない汎用 JSON データを、純粋でシンプルなパブリッシュ/サブスクライブ (pub/sub) パターンで、これらのチャネルのいずれかをリスニングしているクライアントにプッシュできます。

 AWS AppSync を使用して、APIs バックエンドとクライアント側の両方で GraphQL コードを自動的に生成することで、GraphQL の知識がほとんどまたはまったくないシンプルな pub/sub WebSocket API を数分で実装します。

## Pub/sub API を作成して設定する
<a name="aws-appsync-real-time-enhanced-filtering-using-pub-sub-apis"></a>

開始するには、次のことを行います。

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **ダッシュボード**で、**[API の作成]** を選択します。

1. 次の画面で **[リアルタイム API の作成]** を選択し、**[次へ]** を選択します。

1. Pub/sub API のわかりやすい名前を入力します。

1. [プライベート API](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html) 機能を有効にすることもできますが、現時点ではオフにしておくことをおすすめします。[**次へ** ]を選択します。

1. WebSockets を使用して、動作する Pub/sub API を自動的に生成するように選択できます。今のところこの機能はオフにしておくことをおすすめします。[**次へ** ]を選択します。

1. **[API を作成]** を選択し、数分待ってください。アカウントに新しい事前設定された AWS AppSync pub/sub API が作成されます AWS 。

API は、 AWS AppSync の組み込みローカルリゾルバー (ローカルリゾルバーの使用の詳細については、*AWS AppSync デベロッパーガイド*」の[「チュートリアル: ローカルリゾルバー](https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-local-resolvers-js.html)」を参照) を使用して、複数の一時 pub/sub チャネルと WebSocket 接続を管理します。これにより、チャネル名のみに基づいてサブスクライブされたクライアントに自動的にデータが配信およびフィルタリングされます。API コールは API キーを使用して承認されます。

API がデプロイされると、クライアントコードを生成してクライアントアプリケーションと統合するための追加手順がいくつか表示されます。クライアントを素早く統合する方法の例として、このガイドではシンプルな React Web アプリケーションを使用します。

1. まず、ローカルマシンで [NPM](https://www.npmjs.com/get-npm) を使って定型的な React アプリを作成します。

   ```
   $ npx create-react-app mypubsub-app 
   $ cd mypubsub-app
   ```
**注記**  
この例では、[Amplify ライブラリ](https://docs.amplify.aws/lib/)を使用してクライアントをバックエンド API に接続します。ただし、Amplify CLI プロジェクトをローカルで作成する必要はありません。この例では React が最適なクライアントですが、Amplify ライブラリは iOS、Android、Flutter クライアントもサポートしており、これらの異なるランタイムでも同じ機能を提供します。サポートされている Amplify クライアントは、 AWS AppSync GraphQL API バックエンドとやり取りするためのシンプルな抽象化を提供します。これには、AppSync リアルタイム WebSocket プロトコルと完全に互換性がある組み込み WebSocket 機能が含まれます。 [AWS AppSync WebSocket ](https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html)  

   ```
   $ npm install @aws-amplify/api
   ```

1.  AWS AppSync コンソールで **JavaScript** を選択し、**ダウンロード**して API 設定の詳細と生成された GraphQL オペレーションコードを含む単一のファイルをダウンロードします。

1. ダウンロードしたファイルを React プロジェクトの `/src` フォルダーにコピーします。

1. 次に、既存のボイラープレート `src/App.js` ファイルの内容を、コンソールにあるサンプルクライアントコードに置き換えます。

1. 以下のコマンドを使用して、アプリケーションをローカルで構築し起動します。

   ```
   $ npm start
   ```

1. リアルタイムデータの送受信をテストするには、2 つのブラウザーウィンドウを開いて *localhost:3000* にアクセスします。サンプルアプリケーションは、一般的な JSON データを *robots* という名前のハードコードされたチャネルに送信するように設定されています。

1.  ブラウザウィンドウの 1 つで、テキストボックスに次の JSON blob を入力し、**[送信]** をクリックします。

   ```
   {
     "robot":"r2d2",
     "planet": "tatooine"
   }
   ```

どちらのブラウザーインスタンスも *robots* チャンネルに登録され、ウェブアプリケーションの下部に表示される公開データをリアルタイムで受信します。

![\[例: Pub/sub API 用 React アプリ\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/pub-sub-react.png)


スキーマ、リゾルバー、オペレーションなど、必要なすべての GraphQL API コードが自動的に生成され、汎用的な pub/sub ユースケースが可能になります。バックエンドでは、次のような GraphQL ミューテーションを使用してデータが AWS AppSync のリアルタイムエンドポイントに発行されます。

```
mutation PublishData {
    publish(data: "{\"msg\": \"hello world!\"}", name: "channel") {
        data
        name
    }
}
```

サブスクライバーは、関連する GraphQL サブスクリプションを使用して特定の一時チャンネルに送信された公開データにアクセスします。

```
subscription SubscribeToData {
    subscribe(name:"channel") {
        name
        data
    }
}
```

## 既存のアプリケーションへの pub-sub API の実装
<a name="aws-appsync-real-time-enhanced-filtering-existing-apps"></a>

既存のアプリケーションにリアルタイム機能を実装するだけであれば、この汎用的な pub/sub API 構成をあらゆるアプリケーションや API テクノロジーに簡単に統合できます。単一の API エンドポイントを使用して、GraphQL を使用した 1 回のネットワーク呼び出しで 1 つ以上のデータソースのデータに安全にアクセスし、操作し、組み合わせる利点がありますが、 AWS AppSync のリアルタイム機能を活用するために既存の REST ベースのアプリケーションをゼロから変換または再構築する必要はありません。例えば、既存の CRUD ワークロードを別の API エンドポイントに配置し、クライアントは既存のアプリケーションから汎用 pub/sub API に対してリアルタイムおよび pub/sub のみを目的としてメッセージまたはイベントを送受信できます。

# での拡張サブスクリプションフィルターの定義 AWS AppSync
<a name="aws-appsync-real-time-enhanced-filtering"></a>

**重要**  
2025 年 3 月 13 日以降、 AWS AppSync Events を使用して WebSockets を搭載したリアルタイム PubSub API を構築できます。詳細については、「*AWS AppSync Events デベロッパーガイド*」の「[WebSocket 経由でイベントを公開する](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html)」を参照してください。

では AWS AppSync、追加の論理演算子をサポートするフィルターを使用して、GraphQL API サブスクリプションリゾルバーでバックエンドのデータフィルタリングのビジネスロジックを直接定義して有効にできます。クライアントのサブスクリプションクエリで定義されるサブスクリプション引数とは異なり、これらのフィルターは設定できます。サブスクリプション引数の使用の詳細については、「[サブスクリプション引数の使用](aws-appsync-real-time-data.md#using-subscription-arguments)」を参照してください。演算子のリストについては、「[AWS AppSync リゾルバーマッピングテンプレートユーティリティリファレンス](resolver-util-reference.md)」を参照してください。

このドキュメントでは、リアルタイムデータフィルタリングを次のカテゴリに分類します。
+ **基本フィルタリング** - サブスクリプションクエリのクライアント定義引数に基づくフィルタリング。
+ **拡張フィルタリング** - AWS AppSync サービスバックエンドで一元的に定義されたロジックに基づくフィルタリング。

以下のセクションでは、拡張サブスクリプションフィルターの設定方法と、その実際の使用方法について説明します。

## GraphQL スキーマでのサブスクリプションの定義
<a name="aws-appsync-real-time-enhanced-filtering-using-subscription-filters"></a>

拡張サブスクリプションフィルターを使用するには、GraphQL スキーマでサブスクリプションを定義し、次にフィルター拡張機能を使用して拡張フィルターを定義します。拡張サブスクリプションフィルタリングの仕組みを説明するには AWS AppSync、チケット管理システム API を定義する次の GraphQL スキーマを例として使用します。

```
type Ticket {
	id: ID
	createdAt: AWSDateTime
	content: String
	severity: Int
	priority: Priority
	category: String
	group: String
	status: String
	
}

type Mutation {
	createTicket(input: TicketInput): Ticket
}

type Query {
	getTicket(id: ID!): Ticket
}

type Subscription {
	onSpecialTicketCreated: Ticket @aws_subscribe(mutations: ["createTicket"])
	onGroupTicketCreated(group: String!): Ticket @aws_subscribe(mutations: ["createTicket"])
}



enum Priority {
	none
	lowest
	low
	medium
	high
	highest
}

input TicketInput {
	content: String
	severity: Int
	priority: Priority
	category: String
	group: String
```

API `NONE` のデータソースを作成し、このデータソースを使用して `createTicket` ミューテーションにリゾルバーをアタッチするとします。ハンドラーは次のようになります。

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
	return {
		payload: {
			id: util.autoId(),
			createdAt: util.time.nowISO8601(),
			status: 'pending',
			...ctx.args.input,
		},
	};
}

export function response(ctx) {
	return ctx.result;
}
```

**注記**  
拡張フィルターは、特定のサブスクリプションの GraphQL リゾルバーのハンドラーで有効になります。詳細については、「[リゾルバーのリファレンス](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html)」を参照してください。

拡張フィルターの動作を実装するには、`extensions.setSubscriptionFilter()` 関数を使用して、サブスクライブされたクライアントが関心を持つ可能性のある GraphQL ミューテーションからの公開データに対して評価されるフィルター式を定義する必要があります。フィルター拡張機能の詳細については、「[拡張機能](https://docs.aws.amazon.com//appsync/latest/devguide/extensions-js.html)」を参照してください。

次のセクションでは、フィルターを使用して、拡張フィルターを使用する方法について説明します。

## フィルター拡張機能を使用して拡張サブスクリプションフィルターを作成する
<a name="aws-appsync-real-time-enhanced-filtering-defining-filters"></a>

拡張フィルターは、サブスクリプションのリゾルバーのレスポンスハンドラーに JSON で記述されます。フィルターは `filterGroup` というリストにまとめることができます。フィルターは、それぞれフィールド、演算子、値を含む少なくとも 1 つのルールを使用して定義されます。拡張フィルターを設定するための `onSpecialTicketCreated` 向けの新しいリゾルバーを定義しましょう。フィルターには AND ロジックを使用して評価される複数のルールを設定でき、フィルターグループ内の複数のフィルターは OR ロジックを使用して評価されます。

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = {
		or: [
			{ severity: { ge: 7 }, priority: { in: ['high', 'medium'] } },
			{ category: { eq: 'security' }, group: { in: ['admin', 'operators'] } },
		],
	};
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));

  // important: return null in the response
	return null;
}
```

前の例で定義したフィルターに基づいて、チケットが以下のように作成された場合、重要なチケットはサブスクライブされている API クライアントに自動的にプッシュされます。
+ `priority` レベル `high` または `medium`

  AND 
+ `severity` レベル `7`より大きいか等しい (`ge`\$1

OR 
+ `classification` チケットを`Security`に設定 

  AND 
+ `group`アサインを`admin`または`operators`に設定

![\[例: チケットフィルタリングクエリの表示例\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/aws-priority-example.png)


サブスクリプションリゾルバーで定義されたフィルター (拡張フィルター) は、サブスクリプション引数のみに基づくフィルター (基本フィルター) よりも優先されます。サブスクリプション引数の使用について詳しくは、「[サブスクリプション引数の使用](https://docs.aws.amazon.com//appsync/latest/devguide/aws-appsync-real-time-data.html#using-subscription-arguments)」を参照してください。

サブスクリプションの GraphQL スキーマで引数が定義されていて必要な場合、その引数がリゾルバーの `extensions.setSubscriptionFilter()` メソッドでルールとして定義されている場合にのみ、指定された引数に基づくフィルタリングが行われます。ただし、サブスクリプションリゾルバーに `extensions` フィルタリングメソッドがない場合、クライアントで定義された引数は基本的なフィルタリングにのみ使用されます。基本フィルターと拡張フィルターは同時に使用できません。

サブスクリプションのフィルター拡張ロジック内の[`context` 変数を使用して](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)、リクエストに関するコンテキスト情報にアクセスできます。例えば、Amazon Cognito ユーザープール、OIDC、または Lambda カスタムオーソライザーを認可に使用する場合、サブスクリプションが確立されたときに `context.identity` でユーザーに関する情報を取得できます。この情報を使用して、ユーザーの ID に基づいてフィルタを設定できます。

次に、拡張されたフィルタ動作を `onGroupTicketCreated` に実装すると仮定します。`onGroupTicketCreated` サブスクリプションには引数として必須の `group` 名が必要です。チケットを作成すると、自動的に `pending` ステータスが割り当てられます。サブスクリプションフィルターを設定して、指定したグループに属する、新しく作成されたチケットのみを受信できます。

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = { group: { eq: ctx.args.group }, status: { eq: 'pending' } };
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));

	return null;
}
```

以下の例のようにミューテーションを使用してデータが公開された場合:

```
mutation CreateTicket {
  createTicket(input: {priority: medium, severity: 2, group: "aws"}) {
    id
    priority
    severity
    status
    group
    createdAt
  }
}
```

サブスクライブされたクライアントは、`createTicket` ミューテーションを含むチケットが作成されるとすぐに、データが WebSockets を介して自動的にプッシュされるのを待ち受けます。

```
subscription OnGroup {
  onGroupTicketCreated(group: "aws") {
    category
    status
    severity
    priority
    id
    group
    createdAt
    content
  }
}
```

クライアントは引数なしでサブスクライブできます。これは、フィルタリングロジックが拡張フィルタリングを使用して AWS AppSync サービスに実装されるため、クライアントコードが簡素化されるためです。クライアントは、定義されたフィルター条件が満たされた場合にのみデータを受け取ります。

## ネストされたスキーマフィールド用の拡張フィルターの定義
<a name="aws-appsync-real-time-enhanced-filters-nested-schema-fields.title"></a>

強化されたサブスクリプションフィルターを使用して、ネストされたスキーマフィールドをフィルターできます。前のセクションのスキーマをロケーションと住所のタイプを含むように変更したとします。

```
type Ticket {
	id: ID
	createdAt: AWSDateTime
	content: String
	severity: Int
	priority: Priority
	category: String
	group: String
	status: String
	location: ProblemLocation
}

type Mutation {
	createTicket(input: TicketInput): Ticket
}

type Query {
	getTicket(id: ID!): Ticket
}

type Subscription {
	onSpecialTicketCreated: Ticket @aws_subscribe(mutations: ["createTicket"])
	onGroupTicketCreated(group: String!): Ticket @aws_subscribe(mutations: ["createTicket"])
}

type ProblemLocation {
	address: Address
}

type Address {
	country: String
}

enum Priority {
	none
	lowest
	low
	medium
	high
	highest
}

input TicketInput {
	content: String
	severity: Int
	priority: Priority
	category: String
	group: String
	location: AWSJSON
```

このスキーマでは、`.` セパレータを使用してネストを表すことができます。次の例では、`location.address.country` の下にネストされたスキーマフィールドのフィルタルールを追加しています。チケットのアドレスが `USA` に設定されていると、サブスクリプションがトリガーされます。

```
import { util, extensions } from '@aws-appsync/utils';

export const request = (ctx) => ({ payload: null });

export function response(ctx) {
	const filter = {
		or: [
			{ severity: { ge: 7 }, priority: { in: ['high', 'medium'] } },
			{ category: { eq: 'security' }, group: { in: ['admin', 'operators'] } },
			{ 'location.address.country': { eq: 'USA' } },
		],
	};
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));
	return null;
}
```

上の例では、`location` がネストレベル 1、`address` がネストレベル 2、`country` がネストレベル 3 を表しており、これらはすべて `.` セパレータで区切られています。

このサブスクリプションは、`createTicket` ミューテーションを使用してテストできます。

```
mutation CreateTicketInUSA {
  createTicket(input: {location: "{\"address\":{\"country\":\"USA\"}}"}) {
    category
    content
    createdAt
    group
    id
    location {
      address {
        country
      }
    }
    priority
    severity
    status
  }
}
```

## クライアントからの拡張フィルターの定義
<a name="aws-appsync-real-time-enhanced-filtering-defining-from-client"></a>

GraphQL では、[サブスクリプション引数](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html#using-subscription-arguments)を使用して基本的なフィルタリングを使用できます。サブスクリプションクエリで呼び出しを行うクライアントは、引数の値を定義します。`extensions` フィルタリングを使用して AWS AppSync サブスクリプションリゾルバーで拡張フィルターを有効にすると、リゾルバーで定義されたバックエンドフィルターが優先され、優先度が優先されます。

サブスクリプションの `filter` 引数を使用して、クライアント定義の動的な拡張フィルターを設定します。これらのフィルターを設定するときは、新しい引数を反映するように GraphQL スキーマを更新する必要があります。

```
...
type Subscription {
    onSpecialTicketCreated(filter: String): Ticket
        @aws_subscribe(mutations: ["createTicket"])
}
...
```

その後、クライアントは次の例のようにサブスクリプションクエリを送信できます。

```
subscription onSpecialTicketCreated($filter: String) {
     onSpecialTicketCreated(filter: $filter) {
        id
        group
        description
        priority
        severity
     }
 }
```

クエリ変数は、次の例のように設定できます。

```
{"filter" : "{\"severity\":{\"le\":2}}"}
```

`util.transform.toSubscriptionFilter()` リゾルバーユーティリティをサブスクリプション応答マッピングテンプレートに実装すると、サブスクリプション引数で定義されたフィルターを各クライアントに適用できます。

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = ctx.args.filter;
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));
	return null;
}
```

この戦略により、クライアントは拡張フィルタリングロジックと追加の演算子を使用する独自のフィルターを定義できます。フィルターは、特定のクライアントがセキュア WebSocket 接続でサブスクリプションクエリを呼び出すときに割り当てられます。`filter` クエリ変数ペイロードの形式など、拡張フィルタリング用の変換ユーティリティの詳細については、「[JavaScript リゾルバーの概要](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)」を参照してください。

## その他の強化されたフィルタリング制限
<a name="aws-appsync-real-time-enhanced-filtering-additional-restrictions"></a>

拡張フィルターに追加の制限が課されるユースケースを以下に示します。
+ 拡張フィルタは、最上位のオブジェクトリストのフィルタリングをサポートしていません。このユースケースでは、ミューテーションから公開されたデータは拡張サブスクリプションでは無視されます。
+ AWS AppSync は最大 5 レベルのネストをサポートしています。ネストレベル 5 を超えるスキーマフィールドのフィルターは無視されます。以下の GraphQL レスポンスを見てください。`venue.address.country.metadata.continent` の `continent` フィールドはレベル 5 のネストなので許可されています。ただし、`venue.address.country.metadata.capital.financial` の `financial` はレベル 6 のネストなので、フィルターは機能しません。

  ```
  {
      "data": {
          "onCreateFilterEvent": {
              "venue": {
                  "address": {
                      "country": {
                          "metadata": {
                              "capital": {
                                  "financial": "New York"
                              },
                              "continent" : "North America"
                          }
                      },
                      "state": "WA"
                  },
                  "builtYear": 2023
              },
              "private": false,
          }
      }
  }
  ```

# のフィルターを使用した WebSocket 接続のサブスクリプション解除 AWS AppSync
<a name="aws-appsync-real-time-invalidation"></a>

**重要**  
2025 年 3 月 13 日以降、 AWS AppSync Events を使用して WebSockets を搭載したリアルタイム PubSub API を構築できます。詳細については、「*AWS AppSync Events デベロッパーガイド*」の「[WebSocket 経由でイベントを公開する](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html)」を参照してください。

では AWS AppSync、特定のフィルタリングロジックに基づいて、接続されたクライアントから WebSocket 接続を強制的にサブスクリプション解除および終了 (無効化) できます。これは、ユーザーをグループから削除する場合など、承認関連のシナリオで役立ちます。

サブスクリプションの無効化は、ミューテーションで定義されたペイロードに応じて行われます。サブスクリプション接続の無効化に使用されるミューテーションは API の管理操作として扱い、その使用を管理ユーザー、グループ、またはバックエンドサービスに限定して、それに応じて権限の範囲を設定することをおすすめします。例えば、`@aws_auth(cognito_groups: ["Administrators"])` または `@aws_iam` などのスキーマ認可ディレクティブを使用します。詳細については、「[その他の認可モードを使用する](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html#using-additional-authorization-modes)」を参照してください。

無効化フィルターは、[拡張サブスクリプションフィルター](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-enhanced-filtering.html)と同じ構文とロジックを使用します。これらのフィルターは、以下のユーティリティを使用して定義します。
+ `extensions.invalidateSubscriptions()` – GraphQL リゾルバーのミューテーションのレスポンスハンドラーで定義されます。
+ `extensions.setSubscriptionInvalidationFilter()` – ミューテーションにリンクされたサブスクリプションの GraphQL リゾルバーのレスポンスハンドラーで定義されます。

無効化フィルタリング拡張機能の詳細については、「[JavaScript リゾルバーの概要](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)」を参照してください。

## サブスクリプションの無効化の使用
<a name="aws-appsync-real-time-invalidation-using-invalidations"></a>

サブスクリプション無効化の仕組みを確認するには AWS AppSync、次の GraphQL スキーマを使用します。

```
type User {
  userId: ID!
  groupId: ID!
}
    
type Group {
  groupId: ID!
  name: String!
  members: [ID!]!
}

type GroupMessage {
  userId: ID!
  groupId: ID!
  message: String!
}

type Mutation {
    createGroupMessage(userId: ID!, groupId : ID!, message: String!): GroupMessage
    removeUserFromGroup(userId: ID!, groupId : ID!) : User @aws_iam
}

type Subscription {
    onGroupMessageCreated(userId: ID!, groupId : ID!): GroupMessage
        @aws_subscribe(mutations: ["createGroupMessage"])
}

type Query {
	none: String
}
```

`removeUserFromGroup` ミューテーションリゾルバーコードで無効化フィルターを定義します。

```
import { extensions } from '@aws-appsync/utils';

export function request(ctx) {
	return { payload: null };
}

export function response(ctx) {
	const { userId, groupId } = ctx.args;
	extensions.invalidateSubscriptions({
		subscriptionField: 'onGroupMessageCreated',
		payload: { userId, groupId },
	});
	return { userId, groupId };
}
```

ミューテーションが呼び出されると、`payload` オブジェクトに定義されているデータを使用して、`subscriptionField` で定義されたサブスクリプションの購読が解除されます。`onGroupMessageCreated` サスクリプションのレスポンスマッピングテンプレートには無効化フィルターも定義されています。

`extensions.invalidateSubscriptions()` ペイロードに、フィルターで定義されているサブスクライブされたクライアントの ID と一致する ID が含まれている場合、対応するサブスクリプションはサブスクライブ解除されます。さらに、WebSocket 接続は閉じられます。`onGroupMessageCreated` サブスクリプションのサブスクリプションリゾルバーコードを定義します。

```
import { util, extensions } from '@aws-appsync/utils';

export function request(ctx) {
	// simplfy return null for the payload
	return { payload: null };
}

export function response(ctx) {
	const filter = { groupId: { eq: ctx.args.groupId } };
	extensions.setSubscriptionFilter(util.transform.toSubscriptionFilter(filter));

	const invalidation = { groupId: { eq: ctx.args.groupId }, userId: { eq: ctx.args.userId } };
	extensions.setSubscriptionInvalidationFilter(util.transform.toSubscriptionFilter(invalidation));

	return null;
}
```

サブスクリプションレスポンスハンドラーには、サブスクリプションフィルターと無効化フィルターの両方を同時に定義できることに注意してください。

 例えば、クライアント A が次のサブスクリプションリクエストを使用して、その ID `group-1` を持つ新しいユーザーを ID `user-1` のグループにサブスクライブするとします。

```
onGroupMessageCreated(userId : "user-1", groupId: :"group-1"){...}
```

AWS AppSync はサブスクリプションリゾルバーを実行します。これにより、前述の`onGroupMessageCreated`レスポンスマッピングテンプレートで定義されているサブスクリプションフィルターと無効化フィルターが生成されます。クライアント A の場合、サブスクリプションフィルタはへのデータ送信のみを許可し`group-1`、無効化フィルタは `user-1` と `group-1` の両方に定義されます。

ここで、クライアント B が次のサブスクリプションリクエストを使用して、その ID `user-2` を持つユーザーをその ID `group-2`のグループにサブスクライブすると仮定します。

```
onGroupMessageCreated(userId : "user-2", groupId: :"group-2"){...}
```

AWS AppSync はサブスクリプションリゾルバーを実行し、サブスクリプションフィルターと無効化フィルターを生成します。クライアント B の場合、サブスクリプションフィルタはデータ送信先を `group-2` のみを許可し、無効化フィルタは `user-2` と `group-2` の両方に定義されます。

次に、ID `message-1`の付いた新しいグループメッセージが、次の例のようにミューテーションリクエストを使用して作成されると仮定します。

```
createGroupMessage(id: "message-1", groupId :
      "group-1", message: "test message"){...}
```

定義されたフィルターに一致するサブスクライブされたクライアントは、WebSockets を介して次のデータペイロードを自動的に受信します。

```
{
  "data": {
    "onGroupMessageCreated": {
      "id": "message-1",
      "groupId": "group-1",
      "message": "test message",
    }
  }
}
```

フィルター条件が定義済みのサブスクリプションフィルターと一致するため、クライアント A はメッセージを受信します。ただし、ユーザーは `group-1` に参加していないため、クライアント B はメッセージを受信しません。また、リクエストはサブスクリプションリゾルバーで定義されているサブスクリプションフィルターと一致しません。

最後に、`user-1`が次のミューテーションリクエストの使用して `group-1` から削除されたと仮定します。

```
removeUserFromGroup(userId: "user-1", groupId : "group-1"){...}
```

ミューテーションは、`extensions.invalidateSubscriptions()`リゾルバーレスポンスハンドラーコードで定義されているサブスクリプションの無効化を開始します。 AWS AppSync その後、クライアント A のサブスクリプションを解除し、WebSocket 接続を閉じます。ミューテーションで定義された無効化ペイロードがユーザーまたはグループと一致しないため、クライアント B は影響を受けません。

が接続 AWS AppSync を無効にすると、クライアントはサブスクライブ解除されたことを確認するメッセージを受け取ります。

```
{
  "message": "Subscription complete."
}
```

## サブスクリプション無効化フィルターでのコンテキスト変数の使用
<a name="aws-appsync-real-time-invalidation-context"></a>

拡張サブスクリプションフィルターと同様に、サブスクリプション無効化フィルター拡張の[`context`変数](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)を使用して特定のデータにアクセスできます。

例えば、ミューテーションの無効化ペイロードとして E メールアドレスを設定し、そのアドレスを Amazon Cognito ユーザープールまたは OpenID Connect で認証されたサブスクライブユーザーからのメール属性またはクレームと照合することができます。`extensions.setSubscriptionInvalidationFilter()` サブスクリプション無効化ツールで定義された無効化フィルターは、ミューテーションの `extensions.invalidateSubscriptions()` ペイロードによって設定されたメールアドレスが、`context.identity.claims.email` でユーザーの JWT トークンから取得したメールアドレスと一致するかどうかを確認し、無効化を開始します。

# AWS AppSync でのリアルタイム WebSocket クライアントの構築
<a name="real-time-websocket-client"></a>

**重要**  
2025 年 3 月 13 日以降、 AWS AppSync Events を使用して WebSockets を搭載したリアルタイム PubSub API を構築できます。詳細については、「*AWS AppSync Events デベロッパーガイド*」の「[WebSocket 経由でイベントを公開する](https://docs.aws.amazon.com/appsync/latest/eventapi/publish-websocket.html)」を参照してください。

AWS AppSync のリアルタイム WebSocket クライアントは、複数ステップのプロセスを通じて GraphQL サブスクリプションを有効にします。クライアントは、まず AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立し、接続初期化メッセージを送信し、確認を待機します。接続が成功すると、クライアントは一意の IDsと GraphQL クエリで開始メッセージを送信してサブスクリプションを登録します。 AWS AppSync は、成功したサブスクリプションを承認メッセージで確認します。クライアントは、対応するミューテーションの呼び出しによってトリガーされるサブスクリプションイベントを監視します。接続を維持するために、 AWS AppSync は定期的なキープアライブメッセージを送信します。終了すると、クライアントは停止メッセージを送信してサブスクリプションを登録解除します。このシステムは、単一の WebSocket 接続で複数のサブスクリプションをサポートし、API キー、Amazon Cognito ユーザープール、IAM、Lambda など、さまざまな認可モードに対応します。

## GraphQL サブスクリプションのリアルタイム WebSocket クライアント実装
<a name="appsynclong-real-time-websocket-client-implementation-guide-for-graphql-subscriptions"></a>

次のシーケンス図とステップは、WebSocket クライアント、HTTP クライアント、 AWS AppSync 間のリアルタイムサブスクリプションワークフローを示しています。

![\[Sequence diagram showing WebSocket client, AppSync endpoints, and HTTP client interactions for real-time subscriptions.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/realtime-client-flow.png)


1. クライアントは、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立します。ネットワークエラーが発生した場合、クライアントはジッターされたエクスポネンシャルバックオフを行う必要があります。詳細については、 AWS 「 アーキテクチャブログ」の[「エクスポネンシャルバックオフとジッター](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)」を参照してください。

1. (オプション) WebSocket 接続が正常に確立されると、クライアントは `connection_init` メッセージを送信します。

1. が送信されると、クライアント`connection_init`は AWS AppSync からの`connection_ack`メッセージを待機します。このメッセージには、`"ka"` (キープアライブ) メッセージの最大待機時間 (ミリ秒) である `connectionTimeoutMs` パラメータが含まれています。

1. AWS AppSync は定期的に`"ka"`メッセージを送信します。クライアントは、各 `"ka"` メッセージを受信した時間を追跡します。クライアントが `connectionTimeoutMs` ミリ秒以内に `"ka"` メッセージを受信しない場合、クライアントは接続を終了する必要があります。

1. クライアントは、`start` サブスクリプションメッセージを送信してサブスクリプションを登録します。単一の WebSocket 接続では、異なる認可モードであっても、複数のサブスクリプションがサポートされます。

1. クライアントは、 AWS AppSync が成功したサブスクリプションを確認するために`start_ack`メッセージを送信するのを待ちます。エラーが発生した場合、 AWS AppSync は`"type": "error"`メッセージを返します。

1. クライアントは、対応するミューテーションが呼び出された後に送信されるサブスクリプションイベントを監視します。クエリとミューテーションは通常、 AWS AppSync GraphQL エンドポイント`https://`に送信されます。サブスクリプションは、安全な WebSocket () を使用して AWS AppSync リアルタイムエンドポイントを経由します`wss://`。

1. クライアントは、`stop` サブスクリプションメッセージを送信してサブスクリプションを登録解除します。

1. すべてのサブスクリプションを登録解除した後、WebSocket を介して転送されるメッセージがないことを確認した後、クライアントは WebSocket 接続から切断できます。

## WebSocket 接続を確立するためのハンドシェイクの詳細
<a name="handshake-details-to-establish-the-websocket-connection"></a>

 AWS AppSync で正常なハンドシェイクに接続して開始するには、WebSocket クライアントに以下が必要です。
+  AWS AppSync リアルタイムエンドポイント
+ ヘッダー – AWS AppSync エンドポイントと認可に関連する情報が含まれています。 AWS AppSync は、ヘッダーを提供する次の 3 つの方法をサポートしています。
  + クエリ文字列を使用するヘッダー
    + ヘッダー情報は、文字列化された JSON オブジェクトから派生した base64 文字列としてエンコードされます。この JSON オブジェクトには、 AWS AppSync エンドポイントと認可に関連する詳細が含まれています。JSON オブジェクトのコンテンツは、認可モードによって異なります。
  + `Sec-WebSocket-Protocol` 経由のヘッダー
    +  AWS AppSync エンドポイントと認可に関連する情報を含む文字列化された JSON オブジェクトからの base64Url-encodedされた文字列は、`Sec-WebSocket-Protocol`ヘッダーのプロトコルとして渡されます。JSON オブジェクトのコンテンツは、認可モードによって異なります。
  + 標準 HTTP ヘッダー経由のヘッダー:
    + ヘッダーは、GraphQL クエリとミューテーションのヘッダーを AWS AppSync に渡す方法と同様に、接続リクエストで標準 HTTP ヘッダーとして渡すことができます。ただし、標準 HTTP ヘッダーを介してヘッダーを渡すことは、プライベート API 接続リクエストではサポートされていません。
+  `payload` – Base64 でエンコードされた `payload` の文字列。ペイロードは、クエリ文字列を使用してヘッダーが指定されている場合にのみ必要です

これらの必要な詳細情報を使用して、WebSocket クライアントは、WebSocket プロトコルとして `graphql-ws` を使用して、クエリ文字列がある API リアルタイムエンドポイントを含む URL に接続できます。

### GraphQL エンドポイントからの リアルタイムエンドポイントの検出
<a name="discovering-the-appsync-real-time-endpoint-from-the-appsync-graphql-endpoint"></a>

 AWS AppSync GraphQL エンドポイントと AWS AppSync リアルタイムエンドポイントは、プロトコルとドメインがわずかに異なります。( AWS Command Line Interface AWS CLI) コマンド を使用して GraphQL エンドポイントを取得できます`aws appsync get-graphql-api`。

****AWS AppSync GraphQL エンドポイント:****  
 `https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql`

****AWS AppSync リアルタイムエンドポイント:****  
 `wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql`

アプリケーションは、クエリとミューテーションに任意の HTTP クライアントを使用して、 AWS AppSync GraphQL エンドポイント (`https://`) に接続できます。アプリケーションは、サブスクリプション用の任意の WebSocket クライアントを使用して、 AWS AppSync リアルタイムエンドポイント (`wss://`) に接続できます。

カスタムドメイン名を使用すると、1 つのドメインを使用して両方のエンドポイントを操作できます。例えば、カスタムドメインとして `api.example.com` 設定すると、次の URL を使用して GraphQL およびリアルタイムエンドポイントを操作できます。

**AWS AppSync カスタムドメイン GraphQL エンドポイント:**  
`https://api.example.com/graphql`

**AWS AppSync カスタムドメインのリアルタイムエンドポイント:**  
`wss://api.example.com/graphql/realtime`

## AWS AppSync API 認可モードに基づくヘッダーパラメータフォーマット
<a name="header-parameter-format-based-on-appsync-api-authorization-mode"></a>

接続クエリ文字列で使用される`header`オブジェクトの形式は、 AWS AppSync API 認可モードによって異なります。オブジェクトの `host`フィールドは AWS AppSync GraphQL エンドポイントを参照します。これは、リアルタイムエンドポイントに対して`wss://`呼び出しが行われた場合でも、接続を検証するために使用されます。ハンドシェイクを開始し、許可された接続を確立するには、`payload` が空の JSON オブジェクトである必要があります。ペイロードは、ヘッダーがクエリ文字列を介して渡される場合にのみ必要です。

以下のセクションでは、各認可モードのヘッダー形式を示します。

### API キー
<a name="api-key"></a>

#### API キーヘッダー
<a name="api-key-list"></a>

**ヘッダーの内容**
+  `"host": <string>`: AWS AppSync GraphQL エンドポイントまたはカスタムドメイン名のホスト。
+  `"x-api-key": <string>`: AWS AppSync API 用に設定された API キー。

**例**

```
{
    "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com",
    "x-api-key":"da2-12345678901234567890123456"
}
```

**クエリ文字列を使用するヘッダー**

まず、`host` と `x-api-key` を含む JSON オブジェクトが文字列に変換されます。次に、この文字列は base64 エンコードを使用してエンコードされます。結果の base64 エンコードされた文字列は、 AWS AppSync リアルタイムエンドポイントとの接続を確立するための `header` WebSocket URL に という名前のクエリパラメータとして追加されます。結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJob3N0IjoiZXhhbXBsZTEyMzQ1Njc4OTAwMDAuYXBwc3luYy1hcGkudXMtZWFzdC0xLmFtYXpvbmF3cy5jb20iLCJ4LWFtei1kYXRlIjoiMjAyMDA0MDFUMDAxMDEwWiIsIngtYXBpLWtleSI6ImRhMi16NHc0NHZoczV6Z2MzZHRqNXNranJsbGxqaSJ9&payload=e30=
```

base64 でエンコードされたヘッダーオブジェクトに加えて、空の JSON オブジェクト \$1\$1 も base64 でエンコードされ、`payload` という名前の別のクエリパラメータとして WebSocket URL に含まれることに注意してください。

**`Sec-WebSocket-Protocol` 経由のヘッダー**

`host` と `x-api-key` を含む JSON オブジェクトは文字列に変換され、base64Url エンコードを使用してエンコードされます。結果の base64Url でエンコードされた文字列には、`header-` というプレフィックスが付きます。このプレフィックス付き文字列は、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立するときに、 `Sec-WebSocket-Protocol`ヘッダー`graphql-ws`の に加えて新しいサブプロトコルとして使用されます。

結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

`Sec-WebSocket-Protocol` ヘッダーには、次の値が含まれます。

```
"sec-websocket-protocol" : ["graphql-ws", "header-ewogICAgImhvc3QiOiJleGFtcGxlMTIzNDU2Nzg5MDAwMC5hcHBzeW5jLWFwaS51cy1lYXN0LTEuYW1hem9uYXdzLmNvbSIsCiAgICAieC1hcGkta2V5IjoiZGEyLTEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Igp9"]
```

**標準 HTTP ヘッダー経由のヘッダー**

この方法では、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立するときに、ホストと API キーの情報が標準の HTTP ヘッダーを使用して送信されます。結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

リクエストヘッダーには以下が含まれます。

```
"sec-websocket-protocol" : ["graphql-ws"]
"host":"example1234567890000.appsync-api.us-east-1.amazonaws.com",
"x-api-key":"da2-12345678901234567890123456"
```

### Amazon Cognito ユーザープールと OpenID 接続 (OIDC)
<a name="amazon-cognito-user-pools-and-openid-connect-oidc"></a>

#### Amazon Cognito と OIDC ヘッダー
<a name="amazon-cognito-user-pools-and-openid-connect-oidc-list"></a>

ヘッダーの内容:
+  `"Authorization": <string>`: JWT ID トークン。ヘッダーには [Bearer スキーム](https://datatracker.ietf.org/doc/html/rfc6750#section-2.1)を使用できます。
+  `"host": <string>`: AWS AppSync GraphQL エンドポイントまたはカスタムドメイン名のホスト。

例:

```
{
    "Authorization":"eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJHWEFLSXBieU5WNHhsQjEXAMPLEnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyEXAMPLEiJhNmNmMjcwNy0xNjgxLTQ1NDItOWYxOC1lNjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImVkMzM5MmNkLWNjYTMtNGM2OC1hNDYyLTJlZGI3ZTNmY2FjZiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk0NTc3MTgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl83OHY0SVZibVAiLCJleHAiOjE1Njk0NjEzMjAsImlhdCI6MTU2OTQ1NzcyMCwianRpIjoiNTgzZjhmYmMtMzk2MS00YzA4LWJhZTAtYzQyY2IxMTM5NDY5IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1N3RoZWw0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3EXAMPLEn0.B4EXAMPLEFNpJ6ikVp7e6DRee95V6Qi-zEE2DJH7sHOl2zxYi7f-SmEGoh2AD8emxQRYajByz-rE4Jh0QOymN2Ys-ZIkMpVBTPgu-TMWDyOHhDUmUj2OP82yeZ3wlZAtr_gM4LzjXUXmI_K2yGjuXfXTaa1mvQEBG0mQfVd7SfwXB-jcv4RYVi6j25qgow9Ew52ufurPqaK-3WAKG32KpV8J4-Wejq8t0c-yA7sb8EnB551b7TU93uKRiVVK3E55Nk5ADPoam_WYE45i3s5qVAP_-InW75NUoOCGTsS8YWMfb6ecHYJ-1j-bzA27zaT9VjctXn9byNFZmEXAMPLExw",
    "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com"
}
```

**クエリ文字列を使用するヘッダー**

まず、`host` と `Authorization` を含む JSON オブジェクトが文字列に変換されます。次に、この文字列は base64 エンコードを使用してエンコードされます。結果の base64 エンコードされた文字列は、 AWS AppSync リアルタイムエンドポイントとの接続を確立するための `header` WebSocket URL に という名前のクエリパラメータとして追加されます。結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=
```

base64 でエンコードされたヘッダーオブジェクトに加えて、空の JSON オブジェクト \$1\$1 も base64 でエンコードされ、`payload` という名前の別のクエリパラメータとして WebSocket URL に含まれることに注意してください。

**`Sec-WebSocket-Protocol` 経由のヘッダー**

`host` と `Authorization` を含む JSON オブジェクトは文字列に変換され、base64Url エンコードを使用してエンコードされます。結果の base64Url でエンコードされた文字列には、`header-` というプレフィックスが付きます。このプレフィックス付き文字列は、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立するときに、 `Sec-WebSocket-Protocol`ヘッダー`graphql-ws`の に加えて新しいサブプロトコルとして使用されます。

結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

`Sec-WebSocket-Protocol` ヘッダーには、次の値が含まれます。

```
"sec-websocket-protocol" : ["graphql-ws", "header-ewogICAgImhvc3QiOiJleGFtcGxlMTIzNDU2Nzg5MDAwMC5hcHBzeW5jLWFwaS51cy1lYXN0LTEuYW1hem9uYXdzLmNvbSIsCiAgICAieC1hcGkta2V5IjoiZGEyLTEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Igp9"]
```

**標準 HTTP ヘッダー経由のヘッダー**

この方法では、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立するときに、ホストと認可の情報が標準の HTTP ヘッダーを使用して送信されます。結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

リクエストヘッダーには以下が含まれます。

```
"sec-websocket-protocol" : ["graphql-ws"]
"Authorization":"eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJHWEFLSXBieU5WNHhsQjEXAMPLEnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyEXAMPLEiJhNmNmMjcwNy0xNjgxLTQ1NDItOWYxOC1lNjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImVkMzM5MmNkLWNjYTMtNGM2OC1hNDYyLTJlZGI3ZTNmY2FjZiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk0NTc3MTgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl83OHY0SVZibVAiLCJleHAiOjE1Njk0NjEzMjAsImlhdCI6MTU2OTQ1NzcyMCwianRpIjoiNTgzZjhmYmMtMzk2MS00YzA4LWJhZTAtYzQyY2IxMTM5NDY5IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1N3RoZWw0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3EXAMPLEn0.B4EXAMPLEFNpJ6ikVp7e6DRee95V6Qi-zEE2DJH7sHOl2zxYi7f-SmEGoh2AD8emxQRYajByz-rE4Jh0QOymN2Ys-ZIkMpVBTPgu-TMWDyOHhDUmUj2OP82yeZ3wlZAtr_gM4LzjXUXmI_K2yGjuXfXTaa1mvQEBG0mQfVd7SfwXB-jcv4RYVi6j25qgow9Ew52ufurPqaK-3WAKG32KpV8J4-Wejq8t0c-yA7sb8EnB551b7TU93uKRiVVK3E55Nk5ADPoam_WYE45i3s5qVAP_-InW75NUoOCGTsS8YWMfb6ecHYJ-1j-bzA27zaT9VjctXn9byNFZmEXAMPLExw",
"host":"example1234567890000.appsync-api.us-east-1.amazonaws.com"
```

### IAM
<a name="iam"></a>

#### IAM ヘッダー
<a name="iam-list"></a>

**ヘッダーの内容**
+  `"accept": "application/json, text/javascript"`: 定数 `<string>` パラメータ。
+  `"content-encoding": "amz-1.0"`: 定数 `<string>` パラメータ。
+  `"content-type": "application/json; charset=UTF-8"`: 定数 `<string>` パラメータ。
+  `"host": <string>`: これは AWS AppSync GraphQL エンドポイントのホストです。
  + `"x-amz-date": <string>`: タイムスタンプは UTC で、YYYYMMDD'T'HHMMSS'Z' の ISO 8601 形式である必要があります。たとえば、20150830T123600Z は有効なタイムスタンプです。タイムスタンプにミリ秒を含めないでください。詳細については、*AWS 全般のリファレンス* で「[署名バージョン 4 で日付を扱う](https://docs.aws.amazon.com/general/latest/gr/sigv4-date-handling.html)」を参照してください。
  +  `"X-Amz-Security-Token": <string>`: AWS セッショントークン。一時的なセキュリティ認証情報を使用する場合に必要です。詳細については、*IAM ユーザーガイド*の「[AWS リソースを使用した一時的なセキュリティ認証情報の使用](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_credentials_temp_use-resources.html)」を参照してください。
  +  `"Authorization": <string>`: AWS AppSync エンドポイント用の Signature Version 4 (SigV4) 署名情報。署名プロセスの詳細については、「*AWS 全般のリファレンス*」の「[タスク 4: HTTP リクエストに署名を追加する](https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html)」を参照してください。

SigV4 署名の HTTP リクエストには、正規の URL が含まれています。これは AWS AppSync GraphQL エンドポイントに `/connect` が追加されたものです。サービスエンドポイント AWS リージョンは、 AWS AppSync API を使用しているリージョンと同じで、サービス名は「appsync」です。署名する HTTP リクエストは次のとおりです。

```
{
  url: "https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql/connect",
  data: "{}",
  method: "POST",
  headers: {
    "accept": "application/json, text/javascript",
    "content-encoding": "amz-1.0",
    "content-type": "application/json; charset=UTF-8",
  }
}
```

**例**

```
{
  "accept": "application/json, text/javascript",
  "content-encoding": "amz-1.0",
  "content-type": "application/json; charset=UTF-8",
  "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com",
  "x-amz-date": "20200401T001010Z",
  "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==",
  "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=83EXAMPLEbcc1fe3ee69f75cd5ebbf4cb4f150e4f99cec869f149c5EXAMPLEdc"
}
```

**クエリ文字列を使用するヘッダー**

まず、 `host` (AWS AppSync GraphQL エンドポイント) と他の認可ヘッダーを含む JSON オブジェクトが文字列に変換されます。次に、この文字列は base64 エンコードを使用してエンコードされます。結果の base64 エンコードされた文字列は、`header` という名前のクエリパラメータとして WebSocket URL に追加されます。結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=
```

base64 でエンコードされたヘッダーオブジェクトに加えて、空の JSON オブジェクト \$1\$1 も base64 でエンコードされ、`payload` という名前の別のクエリパラメータとして WebSocket URL に含まれることに注意してください。

**`Sec-WebSocket-Protocol` 経由のヘッダー**

`host` およびその他の認可ヘッダーを含む JSON オブジェクトは文字列に変換され、base64Url エンコードを使用してエンコードされます。結果の base64Url でエンコードされた文字列には、`header-` というプレフィックスが付きます。このプレフィックス付き文字列は、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立するときに、 `graphql-ws``Sec-WebSocket-Protocol`ヘッダーの に加えて新しいサブプロトコルとして使用されます。

結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

`Sec-WebSocket-Protocol` ヘッダーには、次の値が含まれます。

```
"sec-websocket-protocol" : ["graphql-ws", "header-ew0KICAiYWNjZXB0IjogImFwcGxpY2F0aW9uL2pzb24sIHRleHQvamF2YXNjcmlwdCIsDQogICJjb250ZW50LWVuY29kaW5nIjogImFtei0xLjAiLA0KICAiY29udGVudC10eXBlIjogImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9VVRGLTgiLA0KICAiaG9zdCI6ICJleGFtcGxlMTIzNDU2Nzg5MDAwMC5hcHBzeW5jLWFwaS51cy1lYXN0LTEuYW1hem9uYXdzLmNvbSIsDQogICJ4LWFtei1kYXRlIjogIjIwMjAwNDAxVDAwMTAxMFoiLA0KICAiWC1BbXotU2VjdXJpdHktVG9rZW4iOiAiQWdFWEFNUExFWjJsdVgyVmpFQW9hRG1Gd0xYTnZkWFJvWldGRVhBTVBMRWN3UlFJZ0FoOTdDbGpxN3dPUEw4S3N4UDNZdER1eWMvOWhBajhQaEo3RnZmMzhTZ29DSVFEaEpFWEFNUExFUHNwaW9PenRqKytwRWFnV0N2ZVpVaktFbjB6eVVoQkVYQU1QTEVqai8vLy8vLy8vLy84QkVYQU1QTEV4T0RrMk5EZ3lOemcxTlNJTW8xbVducEVTV1VvWXc0QmtLcUVGU3JtM0RYdUw4dytaYlZjNEpLakRQNHZVQ0tOUjZMZTlDOXBacDlQc1cwTm9GeTN2TEJVZEFYRVhBTVBMRU9WRzhmZVhmaUVFQSsxa2hnRksvd0V0d1IrOXpGN05hTU1Nc2UwN3dOMmdHMnRIMGVLTUVYQU1QTEVRWCtzTWJ5dFFvOGllcFA5UFpPemxac1NGYi9kUDVROGhrNllFWEFNUExFWWNLWnNUa0RBcTJ1S0ZROG1ZVVZBOUV0UW5OUmlGTEVZODNhS3ZHL3RxTFdObkdsU05WeDdTTWNmb3ZrRkRxUWFtbSs4OHkxT3d3QUVZSzdxY29jZVg2WjdHR2NhWXVJZkdwYVgyTUNDRUxlUXZaKzhXeEVnT25JZno3R1l2c1lOakxaU2FSblY0RytJTFkxRjBRTlc2NFM5TnZqK0J3RGczaHQyQ3JOdnB3alZZbGo5VTNubXhFMFVHNW5lODNMTDVoaHFNcG0yNWttTDdlblZndzJrUXptVTJpZDRJS3UwQy9XYW9EUnVPMkY1ekU2M3ZKYnhOOEFZczczMzgrNEI0SEJiNkJaNk9VZ2c5NlExNVJBNDEvZ0lxeGFWUHh5VHBEZlRVNUdmU0x4b2NkWWVuaXFxcEZNdFpHMm45ZDB1N0dzUU5jRmtOY0czcURabTR0RG84dFpidXltMGEyVmNGMkU1aEZFZ1hCYStYTEpDZlhpLzc3T3FBRWpQMHg3UWRrM0I0M3A4S0cvQmFpb1A1UnNWOHpCR3ZIMXpBZ3lQaGEyck43MC90VDEzeXJtUGQ1UVlFZnd6ZXhqS3JWNG1XSXVSZzhOVEhZU1pKVWFleUN3VG9tODBWRlVKWEcrR1lUVXl2NVcyMmFCY25vUkdpQ2lLRVlUTE9rZ1hlY2RLRlRIbWNJQWVqUTlXZWxyMGExOTZLcTg3dzVLTk1Da2NDR0Zud0JORkxtZm5icE5xVDZyVUJ4eHMzWDVudFg5ZDhIVnRTWUlOVHNHWFhNWkNKN2ZuYldhamhnL2FveDBGdEhYMjFlRjZxSUdUOGoxeitsMm9wVStnZ3dVZ2toVVVnQ0gyVGZxQmorTUxNVlZ2cGdxSnNQS3Q1ODJjYUZLQXJJRkl2Tys5UXVweExuRUgyaHowNFRNVGZuVTZiUUM2ejFidVZlN2grdE9MbmgxWVBGc0xRODhhbmliLzdUVEM4azlEc0JUcTBBU2U4UjJHYlNFc21POXFiYk13Z0VhWVVoT0t0R2V5UXNTSmRoU2s2WHhYVGhyV0w5RW53QkNYRGtJQ01xZG50QXh5eU05bldzWjRiTDlKSHFFeGdXVW1mV0NoelBGQXFuM0Y0eTg5NlVxSFRaeGxxM1dHeXBuNUhIY2VtMkhxZjNJVnhLSDFpbmhxZFZ0a3J5RWlUV3JJN1pkamJxbnFSYmwrV2d0UHRLT093ZURsQ2FSczNSMnFYY2JOZ1ZobGVNazRJV25GOEQxNjk1QWVuVTFMd0hqT0pMa0NqeGdORmlXQUZFUEg5YUVYQU1QTEV4QT09IiwNCiAgIkF1dGhvcml6YXRpb24iOiAiQVdTNC1ITUFDLVNIQTI1NiBDcmVkZW50aWFsPVhYWFhYWFhYWFhYWFhYWFhYWFgvMjAyMDA0MDEvdXMtZWFzdC0xL2FwcHN5bmMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWFjY2VwdDtjb250ZW50LWVuY29kaW5nO2NvbnRlbnQtdHlwZTtob3N0O3gtYW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT04M0VYQU1QTEViY2MxZmUzZWU2OWY3NWNkNWViYmY0Y2I0ZjE1MGU0Zjk5Y2VjODY5ZjE0OWM1RVhBTVBMRWRjIg0KfQ"]
```

**標準 HTTP ヘッダー経由のヘッダー**

この方法では、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立するときに、ホストおよびその他の認可情報が標準の HTTP ヘッダーを使用して送信されます。結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

リクエストヘッダーには以下が含まれます。

```
"sec-websocket-protocol" : ["graphql-ws"]
"accept": "application/json, text/javascript",
"content-encoding": "amz-1.0",
"content-type": "application/json; charset=UTF-8",
"host": "example1234567890000.appsync-api.us-east-1.amazonaws.com",
"x-amz-date": "20200401T001010Z",
"X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==",
"Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=83EXAMPLEbcc1fe3ee69f75cd5ebbf4cb4f150e4f99cec869f149c5EXAMPLEdc"
```

カスタムドメインを使用してリクエストに署名するには

```
{
  url: "https://api.example.com/graphql/connect",
  data: "{}",
  method: "POST",
  headers: {
    "accept": "application/json, text/javascript",
    "content-encoding": "amz-1.0",
    "content-type": "application/json; charset=UTF-8",
  }
}
```

**例**

```
{
  "accept": "application/json, text/javascript",
  "content-encoding": "amz-1.0",
  "content-type": "application/json; charset=UTF-8",
  "host": "api.example.com",
  "x-amz-date": "20200401T001010Z",
  "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==",
  "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=83EXAMPLEbcc1fe3ee69f75cd5ebbf4cb4f150e4f99cec869f149c5EXAMPLEdc"
}
```

**クエリ文字列を含むリクエスト URL**

```
wss://api.example.com/graphql?header=eyEXAMPLEHQiOiJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFEXAMPLEQiLCJjb250ZW50LWVuY29kaW5nIjoEXAMPLEEuMCIsImNvbnRlbnQtdHlwZSI6ImFwcGxpY2F0aW9EXAMPLE47IGNoYXJzZXQ9VVRGLTgiLCJob3N0IjoiZXhhbXBsZEXAMPLENjc4OTAwMDAuYXBwc3luYy1hcGkudXMtZWFzdC0xLmFtYEXAMPLEcy5jb20iLCJ4LWFtei1kYXRlIjoiMjAyMDA0MDFUMDAxMDEwWiIsIlgtEXAMPLElY3VyaXR5LVRva2VuIjoiQWdvSmIzSnBaMmx1WDJWakVBb2FEbUZ3TFhOdmRYUm9aV0Z6ZEMweUlrY3dSUUlnQWg5N0NsanE3d09QTDhLc3hQM1l0RHV5Yy85aEFqOFBoSjdGdmYzOFNnb0NJUURoSllKYkpsbmpQc3Bpb096dGorK3BFYWdXQ3ZlWlVqS0VuMHp5VWhCbXhpck5CUWpqLy8vLy8vLy8vLzhCRUFBYUREY3hPRGsyTkRneU56ZzFOU0lNbzFtV25wRVNXVW9ZdzRCa0txRUZTcm0zRFh1TDh3K1piVmM0SktqRFA0dlVDS05SNkxlOUM5cFpwOVBzVzBOb0Z5M3ZMQlVkQVh3dDZQSld1T1ZHOGZlWGZpRUVBKzFraGdGSy93RXR3Uis5ekY3TmFNTU1zZTA3d04yZ0cydEgwZUtNVFhuOEF3QVFYK3NNYnl0UW84aWVwUDlQWk96bFpzU0ZiL2RQNVE4aGs2WWpHVGFMMWVZY0tac1RrREFxMnVLRlE4bVlVVkE5RXRRbk5SaUZMRVk4M2FLdkcvdHFMV05uR2xTTlZ4N1NNY2ZvdmtGRHFRYW1tKzg4eTFPd3dBRVlLN3Fjb2NlWDZaN0dHY2FZdUlmR3BhWDJNQ0NFTGVRdlorOFd4RWdPbklmejdHWXZzWU5qTFpTYVJuVjRHK0lMWTFGMFFOVzY0UzlOdmorQndEZzNodDJDck52cHdqVllsajlVM25teEUwVUc1bmU4M0xMNWhocU1wbTI1a21MN2VuVmd3MmtRem1VMmlkNElLdTBDL1dhb0RSdU8yRjV6RTYzdkpieE44QVlzNzMzOCs0QjRIQmI2Qlo2T1VnZzk2UTE1UkE0MS9nSXF4YVZQeHlUcERmVFU1R2ZTTHhvY2RZZW5pcXFwRk10WkcybjlkMHU3R3NRTmNGa05jRzNxRFptNHREbzh0WmJ1eW0wYTJWY0YyRTVoRkVnWEJhK1hMSkNmWGkvNzdPcUFFalAweDdRZGszQjQzcDhLRy9CYWlvUDVSc1Y4ekJHdkgxekFneVBoYTJyTjcwL3RUMTN5cm1QZDVRWUVmd3pleGpLclY0bVdJdVJnOE5USFlTWkpVYWV5Q3dUb204MFZGVUpYRytHWVRVeXY1VzIyYUJjbm9SR2lDaUtFWVRMT2tnWGVjZEtGVEhtY0lBZWpROVdlbHIwYTE5NktxODd3NUtOTUNrY0NHRm53Qk5GTG1mbmJwTnFUNnJVQnh4czNYNW50WDlkOEhWdFNZSU5Uc0dYWE1aQ0o3Zm5iV2FqaGcvYW94MEZ0SFgyMWVGNnFJR1Q4ajF6K2wyb3BVK2dnd1Vna2hVVWdDSDJUZnFCaitNTE1WVnZwZ3FKc1BLdDU4MmNhRktBcklGSXZPKzlRdXB4TG5FSDJoejA0VE1UZm5VNmJRQzZ6MWJ1VmU3aCt0T0xuaDFZUEZzTFE4OGFuaWIvN1RUQzhrOURzQlRxMEFTZThSMkdiU0VzbU85cWJiTXdnRWFZVWhPS3RHZXlRc1NKZGhTazZYeFhUaHJXTDlFbndCQ1hEa0lDTXFkbnRBeHl5TTluV3NaNGJMOUpIcUV4Z1dVbWZXQ2h6UEZBcW4zRjR5ODk2VXFIVFp4bHEzV0d5cG41SEhjZW0ySHFmM0lWeEtIMWluaHFkVnRrcnlFaVRXckk3WmRqYnFucVJibCtXZ3RQdEtPT3dlRGxDYVJzM1IycVhjYk5nVmhsZU1rNElXbkY4RDE2OTVBZW5VMUx3SGpPSkxrQ2p4Z05GaVdBRkVQSDlhTklhcXMvWnhBPT0iLCJBdXRob3JpemF0aW9uIjoiQVdTNC1ITUFDLVNIQTI1NiBDcmVkZW50aWFsPVhYWFhYWFhYWFhYWFhYWFhYWFgvMjAxOTEwMDIvdXMtZWFzdC0xEXAMPLE5bmMvYXdzNF9yZXF1ZXN0LCBTaWduZWRIZWFkZXJzPWFjY2VwdDtjb250ZWEXAMPLE29kaW5nO2NvbnRlbnQtdHlwZTtob3EXAMPLEW16LWRhdGU7eC1hbXotc2VjdXJpdHktdG9rZW4sIFNpZ25hdHVyZT04MzE4EXAMPLEiY2MxZmUzZWU2OWY3NWNkEXAMPLE0Y2I0ZjE1MGU0Zjk5Y2VjODY5ZjE0OWM1ZDAzNDEXAMPLEn0=&payload=e30=
```

**注記**  
1 つの WebSocket 接続には、(異なる認証モードであっても) 複数のサブスクリプションを設定できます。これを実装する 1 つの方法は、最初のサブスクリプション用の WebSocket 接続を作成し、最後のサブスクリプションが登録解除されたときにそれを閉じることです。最後のサブスクリプションが登録解除された直後にアプリケーションがサブスクライブされた場合に備えて、WebSocket 接続を閉じる前に数秒待つことで最適化できます。モバイルアプリの例では、ある画面から別の画面に変更するとき、*アンマウント*イベントでは、サブスクリプションを停止し、*マウント*イベントでは、別のサブスクリプションを開始します。

### Lambda 認可
<a name="lambda-auth"></a>

#### Lambda 認可ヘッダー
<a name="lambda-auth-list"></a>

**ヘッダーの内容**
+  `"Authorization": <string>`:`authorizationToken` として渡される値。
+  `"host": <string>`: AWS AppSync GraphQL エンドポイントまたはカスタムドメイン名のホスト。

**例**

```
{
    "Authorization":"M0UzQzM1MkQtMkI0Ni00OTZCLUI1NkQtMUM0MTQ0QjVBRTczCkI1REEzRTIxLTk5NzItNDJENi1BQjMwLTFCNjRFNzQ2NzlCNQo=",
    "host":"example1234567890000.appsync-api.us-east-1.amazonaws.com"
}
```

**クエリ文字列を使用するヘッダー**

まず、`host` と `Authorization` を含む JSON オブジェクトが文字列に変換されます。次に、この文字列は base64 エンコードを使用してエンコードされます。結果の base64 エンコードされた文字列は、 AWS AppSync リアルタイムエンドポイントとの接続を確立するための `header` WebSocket URL に という名前のクエリパラメータとして追加されます。結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql?header=eyJBdXRob3JpemF0aW9uIjoiZXlKcmFXUWlPaUpqYkc1eGIzQTVlVzVNSzA5UVlYSXJNVEpIV0VGTFNYQmllVTVXTkhoc1FqaFBWVzlZTW5NMldsZHZQU0lzSW1Gc1p5STZJbEpUTWpVMkluMC5leUp6ZFdJaU9pSmhObU5tTWpjd055MHhOamd4TFRRMU5ESXRPV1l4T0MxbE5qWTBNVGcyTmpsa016WWlMQ0psZG1WdWRGOXBaQ0k2SW1Wa016TTVNbU5rTFdOallUTXROR00yT0MxaE5EWXlMVEpsWkdJM1pUTm1ZMkZqWmlJc0luUnZhMlZ1WDNWelpTSTZJbUZqWTJWemN5SXNJbk5qYjNCbElqb2lZWGR6TG1OdloyNXBkRzh1YzJsbmJtbHVMblZ6WlhJdVlXUnRhVzRpTENKaGRYUm9YM1JwYldVaU9qRTFOamswTlRjM01UZ3NJbWx6Y3lJNkltaDBkSEJ6T2x3dlhDOWpiMmR1YVhSdkxXbGtjQzVoY0MxemIzVjBhR1ZoYzNRdE1pNWhiV0Y2YjI1aGQzTXVZMjl0WEM5aGNDMXpiM1YwYUdWaGMzUXRNbDgzT0hZMFNWWmliVkFpTENKbGVIQWlPakUxTmprME5qRXpNakFzSW1saGRDSTZNVFUyT1RRMU56Y3lNQ3dpYW5ScElqb2lOVGd6WmpobVltTXRNemsyTVMwMFl6QTRMV0poWlRBdFl6UXlZMkl4TVRNNU5EWTVJaXdpWTJ4cFpXNTBYMmxrSWpvaU0zRmxhalZsTVhabU16ZDFOM1JvWld3MGRHOTFkREprTVd3aUxDSjFjMlZ5Ym1GdFpTSTZJbVZzYjNKNllXWmxJbjAuQjRjZEp0aDNLRk5wSjZpa1ZwN2U2RFJlZTk1VjZRaS16RUUyREpIN3NIT2wyenhZaTdmLVNtRUdvaDJBRDhlbXhRUllhakJ5ei1yRTRKaDBRT3ltTjJZcy1aSWtNcFZCVFBndS1UTVdEeU9IaERVbVVqMk9QODJ5ZVozd2xaQXRyX2dNNEx6alhVWG1JX0syeUdqdVhmWFRhYTFtdlFFQkcwbVFmVmQ3U2Z3WEItamN2NFJZVmk2ajI1cWdvdzlFdzUydWZ1clBxYUstM1dBS0czMktwVjhKNC1XZWpxOHQwYy15QTdzYjhFbkI1NTFiN1RVOTN1S1JpVlZLM0U1NU5rNUFEUG9hbV9XWUU0NWkzczVxVkFQXy1Jblc3NU5Vb09DR1RzUzhZV01mYjZlY0hZSi0xai1iekEyN3phVDlWamN0WG45YnlORlptS0xwQTJMY3h3IiwiaG9zdCI6ImV4YW1wbGUxMjM0NTY3ODkwMDAwLmFwcHN5bmMtYXBpLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tIn0=&payload=e30=
```

base64 でエンコードされたヘッダーオブジェクトに加えて、空の JSON オブジェクト \$1\$1 も base64 でエンコードされ、`payload` という名前の別のクエリパラメータとして WebSocket URL に含まれることに注意してください。

**`Sec-WebSocket-Protocol` 経由のヘッダー**

`host` と `Authorization` を含む JSON オブジェクトは文字列に変換され、base64Url エンコードを使用してエンコードされます。結果の base64Url でエンコードされた文字列には、`header-` というプレフィックスが付きます。このプレフィックス付き文字列は、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立するときに、 `Sec-WebSocket-Protocol`ヘッダー`graphql-ws`の に加えて新しいサブプロトコルとして使用されます。

結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

`Sec-WebSocket-Protocol` ヘッダーには、次の値が含まれます。

```
"sec-websocket-protocol" : ["graphql-ws", "header-ewogICAgImhvc3QiOiJleGFtcGxlMTIzNDU2Nzg5MDAwMC5hcHBzeW5jLWFwaS51cy1lYXN0LTEuYW1hem9uYXdzLmNvbSIsCiAgICAieC1hcGkta2V5IjoiZGEyLTEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Igp9"]
```

**標準 HTTP ヘッダー経由のヘッダー**

この方法では、 AWS AppSync リアルタイムエンドポイントとの WebSocket 接続を確立するときに、ホストと認可の情報が標準の HTTP ヘッダーを使用して送信されます。結果のリクエスト URL は次の形式です。

```
wss://example1234567890000.appsync-realtime-api.us-east-1.amazonaws.com/graphql
```

リクエストヘッダーには以下が含まれます。

```
"sec-websocket-protocol" : ["graphql-ws"]
"Authorization":"eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJHWEFLSXBieU5WNHhsQjEXAMPLEnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyEXAMPLEiJhNmNmMjcwNy0xNjgxLTQ1NDItOWYxOC1lNjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImVkMzM5MmNkLWNjYTMtNGM2OC1hNDYyLTJlZGI3ZTNmY2FjZiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk0NTc3MTgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMl83OHY0SVZibVAiLCJleHAiOjE1Njk0NjEzMjAsImlhdCI6MTU2OTQ1NzcyMCwianRpIjoiNTgzZjhmYmMtMzk2MS00YzA4LWJhZTAtYzQyY2IxMTM5NDY5IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1N3RoZWw0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3EXAMPLEn0.B4EXAMPLEFNpJ6ikVp7e6DRee95V6Qi-zEE2DJH7sHOl2zxYi7f-SmEGoh2AD8emxQRYajByz-rE4Jh0QOymN2Ys-ZIkMpVBTPgu-TMWDyOHhDUmUj2OP82yeZ3wlZAtr_gM4LzjXUXmI_K2yGjuXfXTaa1mvQEBG0mQfVd7SfwXB-jcv4RYVi6j25qgow9Ew52ufurPqaK-3WAKG32KpV8J4-Wejq8t0c-yA7sb8EnB551b7TU93uKRiVVK3E55Nk5ADPoam_WYE45i3s5qVAP_-InW75NUoOCGTsS8YWMfb6ecHYJ-1j-bzA27zaT9VjctXn9byNFZmEXAMPLExw",
"host":"example1234567890000.appsync-api.us-east-1.amazonaws.com"
```

## リアルタイム WebSocket オペレーション
<a name="real-time-websocket-operation"></a>

 AWS AppSync で成功した WebSocket ハンドシェイクを開始した後、クライアントは後続のメッセージを送信して、異なるオペレーションのために AWS AppSync に接続する必要があります。これらのメッセージには、次のデータが必要です。
+  `type`: 操作のタイプ。
+  `id`: サブスクリプションの一意の識別子。この目的のために UUID を使用することをお勧めします。
+  `payload`: オペレーションタイプに応じて、関連付けられたペイロード。

`id` フィールド `type` とフィールドはオプションで、`payload` フィールドは必須です。

### イベントのシーケンス
<a name="sequence-of-events"></a>

サブスクリプションリクエストを正常に開始、確立、登録、および処理するには、クライアントは次のシーケンスを実行する必要があります。

1. 接続の初期化 (`connection_init`)

1. 接続確認応答 (`connection_ack`)

1. サブスクリプション登録 (`start`)

1. サブスクリプション確認応答 (`start_ack`)

1. サブスクリプションの処理 (`data`)

1. サブスクリプションの登録解除 (`stop`)

## 接続初期化メッセージ
<a name="connection-init-message"></a>

(オプション) ハンドシェイクが成功すると、クライアントは`connection_init`メッセージを送信して AWS AppSync リアルタイムエンドポイントとの通信を開始できます。メッセージは、次のように JSON オブジェクトを文字列化することによって得られる文字列です。

```
{ "type": "connection_init" }
```

## 接続確認メッセージ
<a name="connection-acknowledge-message"></a>

`connection_init` メッセージを送信した後、クライアントは `connection_ack` メッセージを待つ必要があります。`connection_ack` を受信前に送信されたメッセージはすべて無視されます。メッセージは次のように表示されるはずです。

```
{
  "type": "connection_ack",
  "payload": {
    // Time in milliseconds waiting for ka message before the client should terminate the WebSocket connection
    "connectionTimeoutMs": 300000
  }
}
```

## キープアライブメッセージ
<a name="keep-alive-message"></a>

接続確認メッセージに加えて、クライアントは定期的にキープアライブメッセージを受信します。接続タイムアウト期間内にクライアントがキープアライブメッセージを受信しない場合、クライアントは接続を閉じる必要があります。 AWS AppSync は、接続を自動的にシャットダウンするまで (24 時間後）、これらのメッセージを送信し、登録されたサブスクリプションを処理し続けます。キープアライブメッセージはハートビートであり、クライアントによる確認は不要です。

```
{ "type": "ka" }
```

## サブスクリプション登録メッセージ
<a name="subscription-registration-message"></a>

クライアントが`connection_ack`メッセージを受信すると、クライアントはサブスクリプション登録メッセージを AWS AppSync に送信できます。このタイプのメッセージは、以下のフィールドを含む文字列化された JSON オブジェクトです。
+  サブスクリプションの ID。この ID はサブスクリプションごとに一意である必要があります。そうしないと、サーバーはサブスクリプション ID が重複していることを示すエラーを返します。
+  `"type": "start"`: 定数 `<string>` パラメータ。
+  `"payload": <Object>`: サブスクリプションに関連する情報が含むオブジェクト。
  +  `"data": <string>`: GraphQL クエリと変数を含む文字列化された JSON オブジェクト。
    +  `"query": <string>`: GraphQL オペレーション。
    +  `"variables": <Object>`: クエリの変数を含むオブジェクト。
  +  `"extensions": <Object>`: 認可オブジェクトを含むオブジェクト。
+  `"authorization": <Object>`: 認可に必要なフィールドが含むオブジェクト。

### サブスクリプション登録の認可オブジェクト
<a name="authorization-object-for-subscription-registration"></a>

また、[AWS AppSync API 認可モードに基づくヘッダーパラメータフォーマット](#header-parameter-format-based-on-appsync-api-authorization-mode) セクションにある同じルールが認可オブジェクトに適用されます。唯一の例外は IAM で、SigV4 署名情報がわずかに異なります。詳細については、IAM の例を参照してください。

Amazon Cognito ユーザープールの使用例:

```
{
  "id": "ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69",
  "payload": {
    "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}",
      "extensions": {
        "authorization": {
          "Authorization": "eyEXAMPLEiJjbG5xb3A5eW5MK09QYXIrMTJEXAMPLEBieU5WNHhsQjhPVW9YMnM2WldvPSIsImFsZyI6IlEXAMPLEn0.eyJzdWIiOiJhNmNmMjcwNy0xNjgxLTQ1NDItEXAMPLENjY0MTg2NjlkMzYiLCJldmVudF9pZCI6ImU3YWVmMzEyLWUEXAMPLEY0Zi04YjlhLTRjMWY5M2Q5ZTQ2OCIsInRva2VuX3VzZSI6ImFjY2VzcyIsIEXAMPLEIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Njk2MTgzMzgsImlzcyI6Imh0dEXAMPLEXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMi5hbWF6b25hd3MuY29tXC9hcC1zbEXAMPLEc3QtMl83OHY0SVZibVAiLCJleHAiOjE1NzAyNTQ3NTUsImlhdCI6MTU3MDI1MTE1NSwianRpIjoiMmIEXAMPLEktZTVkMi00ZDhkLWJiYjItNjA0YWI4MDEwOTg3IiwiY2xpZW50X2lkIjoiM3FlajVlMXZmMzd1EXAMPLE0dG91dDJkMWwiLCJ1c2VybmFtZSI6ImVsb3J6YWZlIn0.CT-qTCtrYeboUJ4luRSTPXaNewNeEXAMPLE14C6sfg05tO0fOMpiUwj9k19gtNCCMqoSsjtQoUweFnH4JYa5EXAMPLEVxOyQEQ4G7jQrt5Ks6STn53vuseR3zRW9snWgwz7t3ZmQU-RWvW7yQU3sNQRLEXAMPLEcd0yufBiCYs3dfQxTTdvR1B6Wz6CD78lfNeKqfzzUn2beMoup2h6EXAMPLE4ow8cUPUPvG0DzRtHNMbWskjPanu7OuoZ8iFO_Eot9kTtAlVKYoNbWkZhkD8dxutyoU4RSH5JoLAnrGF5c8iKgv0B2dfEXAMPLEIihxaZVJ9w9w48S4EXAMPLEcA",
          "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com"
         }
      }
  },
  "type": "start"
}
```

IAM の使用例:

```
{
  "id": "eEXAMPLE-cf23-1234-5678-152EXAMPLE69",
  "payload": {
    "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}",
    "extensions": {
      "authorization": {
        "accept": "application/json, text/javascript",
        "content-type": "application/json; charset=UTF-8",
        "X-Amz-Security-Token": "AgEXAMPLEZ2luX2VjEAoaDmFwLXNvdXRoZWFEXAMPLEcwRQIgAh97Cljq7wOPL8KsxP3YtDuyc/9hAj8PhJ7Fvf38SgoCIQDhJEXAMPLEPspioOztj++pEagWCveZUjKEn0zyUhBEXAMPLEjj//////////8BEXAMPLExODk2NDgyNzg1NSIMo1mWnpESWUoYw4BkKqEFSrm3DXuL8w+ZbVc4JKjDP4vUCKNR6Le9C9pZp9PsW0NoFy3vLBUdAXEXAMPLEOVG8feXfiEEA+1khgFK/wEtwR+9zF7NaMMMse07wN2gG2tH0eKMEXAMPLEQX+sMbytQo8iepP9PZOzlZsSFb/dP5Q8hk6YEXAMPLEYcKZsTkDAq2uKFQ8mYUVA9EtQnNRiFLEY83aKvG/tqLWNnGlSNVx7SMcfovkFDqQamm+88y1OwwAEYK7qcoceX6Z7GGcaYuIfGpaX2MCCELeQvZ+8WxEgOnIfz7GYvsYNjLZSaRnV4G+ILY1F0QNW64S9Nvj+BwDg3ht2CrNvpwjVYlj9U3nmxE0UG5ne83LL5hhqMpm25kmL7enVgw2kQzmU2id4IKu0C/WaoDRuO2F5zE63vJbxN8AYs7338+4B4HBb6BZ6OUgg96Q15RA41/gIqxaVPxyTpDfTU5GfSLxocdYeniqqpFMtZG2n9d0u7GsQNcFkNcG3qDZm4tDo8tZbuym0a2VcF2E5hFEgXBa+XLJCfXi/77OqAEjP0x7Qdk3B43p8KG/BaioP5RsV8zBGvH1zAgyPha2rN70/tT13yrmPd5QYEfwzexjKrV4mWIuRg8NTHYSZJUaeyCwTom80VFUJXG+GYTUyv5W22aBcnoRGiCiKEYTLOkgXecdKFTHmcIAejQ9Welr0a196Kq87w5KNMCkcCGFnwBNFLmfnbpNqT6rUBxxs3X5ntX9d8HVtSYINTsGXXMZCJ7fnbWajhg/aox0FtHX21eF6qIGT8j1z+l2opU+ggwUgkhUUgCH2TfqBj+MLMVVvpgqJsPKt582caFKArIFIvO+9QupxLnEH2hz04TMTfnU6bQC6z1buVe7h+tOLnh1YPFsLQ88anib/7TTC8k9DsBTq0ASe8R2GbSEsmO9qbbMwgEaYUhOKtGeyQsSJdhSk6XxXThrWL9EnwBCXDkICMqdntAxyyM9nWsZ4bL9JHqExgWUmfWChzPFAqn3F4y896UqHTZxlq3WGypn5HHcem2Hqf3IVxKH1inhqdVtkryEiTWrI7ZdjbqnqRbl+WgtPtKOOweDlCaRs3R2qXcbNgVhleMk4IWnF8D1695AenU1LwHjOJLkCjxgNFiWAFEPH9aEXAMPLExA==",
        "Authorization": "AWS4-HMAC-SHA256 Credential=XXXXXXXXXXXXXXXXXXXX/20200401/us-east-1/appsync/aws4_request, SignedHeaders=accept;content-encoding;content-type;host;x-amz-date;x-amz-security-token, Signature=b90131a61a7c4318e1c35ead5dbfdeb46339a7585bbdbeceeaff51f4022eb1fd",
        "content-encoding": "amz-1.0",
        "host": "example1234567890000.appsync-api.us-east-1.amazonaws.com",
        "x-amz-date": "20200401T001010Z"
      }
    }
  },
  "type": "start"
}
```

カスタムドメイン名の使用例

```
{
  "id": "key-cf23-4cb8-9fcb-152ae4fd1e69",
  "payload": {
    "data": "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}",
      "extensions": {
        "authorization": {
          "x-api-key": "da2-12345678901234567890123456",
          "host": "api.example.com"
         }
      }
  },
  "type": "start"
}
```

SigV4 署名は、URL に `/connect` を追加する必要がなく、`data` は JSON 文字列化された GraphQL オペレーションに置き換えられます。次に、SigV4 署名リクエストの例を示します。

```
{
  url: "https://example1234567890000.appsync-api.us-east-1.amazonaws.com/graphql",
  data: "{\"query\":\"subscription onCreateMessage {\\n onCreateMessage {\\n __typename\\n message\\n }\\n }\",\"variables\":{}}",
  method: "POST",
  headers: {
    "accept": "application/json, text/javascript",
    "content-encoding": "amz-1.0",
    "content-type": "application/json; charset=UTF-8",
  }
}
```

## サブスクリプション確認メッセージ
<a name="subscription-acknowledge-message"></a>

サブスクリプション開始メッセージを送信した後、クライアントは AWS AppSync が`start_ack`メッセージを送信するのを待つ必要があります。`start_ack` メッセージでは、サブスクリプションが成功したことが示されます。

サブスクリプション確認の例

```
{
  "type": "start_ack",
  "id": "eEXAMPLE-cf23-1234-5678-152EXAMPLE69"
}
```

## エラーメッセージ
<a name="error-message"></a>

接続の初期化またはサブスクリプションの登録が失敗した場合、またはサブスクリプションがサーバーから終了された場合、サーバーはエラーメッセージをクライアントに送信します。接続の開始時間中にエラーが発生した場合、接続はサーバーによって閉じられます。
+  `"type": "error"`: 定数 `<string>` パラメータ。
+  `"id": <string>`: 対応する登録済みサブスクリプションの ID (該当する場合)。
+  `"payload" <Object>`: 対応するエラー情報を含むオブジェクト。

例:

```
{
  "type": "error",
  "payload": {
    "errors": [
      {
        "errorType": "LimitExceededError",
        "message": "Rate limit exceeded"
      }
    ]
  }
}
```

## データメッセージの処理
<a name="processing-data-messages"></a>

クライアントがミューテーションを送信すると、 AWS AppSync はミューテーションに関心のあるすべてのサブスクライバーを識別し、`"start"`サブスクリプションオペレーション`id`から対応するサブスクリプションを使用して各サブスクライバーに`"type":"data"`メッセージを送信します。クライアントは、データメッセージを受信したときに、対応するサブスクリプションと照合できるように、送信するサブスクリプション `id` を追跡する必要があります。
+  `"type": "data"`: 定数 `<string>` パラメータ。
+  `"id": <string>`: 対応する登録済みサブスクリプションの ID。
+  `"payload" <Object>`: サブスクリプション情報を含むオブジェクト。

例:

```
{
  "type": "data",
  "id": "ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69",
  "payload": {
    "data": {
      "onCreateMessage": {
        "__typename": "Message",
        "message": "test"
      }
    }
  }
}
```

## サブスクリプションの登録解除メッセージ
<a name="subscription-unregistration-message"></a>

アプリがサブスクリプションイベントのリッスンを停止する場合、クライアントは次の文字列化された JSON オブジェクトを含むメッセージを送信する必要があります。
+  `"type": "stop"`: 定数 `<string>` パラメータ。
+  `"id": <string>`: 登録を解除するサブスクリプションの ID。

例:

```
{
  "type":"stop",
  "id":"ee849ef0-cf23-4cb8-9fcb-152ae4fd1e69"
}
```

AWS AppSync は、次の文字列化された JSON オブジェクトを含む確認メッセージを送信します。
+  `"type": "complete"`: 定数 `<string>` パラメータ。
+  `"id": <string>`: 登録を解除したサブスクリプションの ID。

クライアントは確認メッセージを受信すると、この特定のサブスクリプションに関するメッセージをそれ以上受信しません。

例:

```
{
  "type":"complete",
  "id":"eEXAMPLE-cf23-1234-5678-152EXAMPLE69"
}
```

## WebSocket の切断
<a name="disconnecting-the-websocket"></a>

切断する前に、クライアントは、データ損失を避けるために、WebSocket 接続を介して現在オペレーションが行われていないことを確認するために必要なロジックを持っている必要があります。WebSocket から切断する前に、すべてのサブスクリプションを登録解除する必要があります。

# での APIsマージ AWS AppSync
<a name="merged-api"></a>

組織内で GraphQL の使用が拡大するにつれて、API の使いやすさと API の開発速度の間でトレードオフが生じる可能性があります。一方、組織はアプリケーション開発を簡素化するために AWS AppSync と GraphQL を採用しています。これにより、開発者は柔軟な API を使用して、1 つ以上のデータドメインのデータに 1 回のネットワーク呼び出しで安全にアクセスし、操作し、組み合わせることができます。一方、1 つの GraphQL API エンドポイントにまとめられたさまざまなデータドメインを担当する組織内のチームは、相互に独立して API 更新を作成、管理、デプロイできる場合があります。これにより、開発速度が向上します。

この緊張を解決するために、 AWS AppSync Merged APIs機能を使用すると、さまざまなデータドメインのチームが個別に AWS AppSync APIs (GraphQL スキーマ、リゾルバー、データソース、関数など) を作成してデプロイし、1 つのマージされた API に結合できます。これにより、組織は使いやすいクロスドメイン API を維持できるようになり、その API に貢献するさまざまなチームが API を迅速かつ独立して更新できるようになります。

次の図は、マージされた API ワークフローを示しています。

![\[1 つのマージされた API エンドポイントに複数のソース APIsが結合されているマージされた API ワークフローを示す図\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/merged-api-workflow.png)


Merged APIs を使用すると、組織は複数の独立したソース AWS AppSync APIsのリソースを単一の AWS AppSync Merged API エンドポイントにインポートできます。これを行うには、 AWS AppSync で AWS AppSync APIs のリストを作成し、スキーマ、タイプ、データソース、リゾルバー、関数など、ソース APIs に関連付けられたすべてのメタデータを新しいマージされた API に AWS AppSync マージできます。

マージ中は、複数のスキーマを組み合わせる際の型名の競合など、ソース API のデータ内容の不一致が原因でマージによる競合が発生する可能性があります。ソース API の定義が競合しない単純なユースケースでは、ソース API スキーマを変更する必要はありません。結果として得られる Merged API は、元の AWS AppSync APIs からすべてのタイプ、リゾルバー、データソース、関数をインポートするだけです。競合が発生する複雑なユースケースでは、ユーザー/チームはさまざまな方法で競合を解決する必要があります。 は、マージ競合を軽減できるいくつかのツールと例をユーザー AWS AppSync に提供します。

で設定された後続のマージ AWS AppSync は、ソース APIs で行われた変更を関連する Merged API に伝達します。

## Merged API とフェデレーション
<a name="merged-api-federation"></a>

GraphQL コミュニティには、GraphQL スキーマを結合し、共有グラフを通じてチームコラボレーションを可能にするための多くのソリューションとパターンがあります。 AWS AppSync マージされた APIsはスキーマ構成に*ビルド時間の*アプローチを採用しており、ソース APIs は別の Merged API に結合されます。別の方法として、*ランタイム*ルーターを複数のソース API またはサブグラフに重ねる方法があります。このアプローチでは、ルーターはリクエストを受け取り、メタデータとして維持する結合スキーマを参照し、リクエストプランを構築し、基盤となるサブグラフ/サーバーにリクエスト要素を分散します。次の表は、GraphQL スキーマ構成に対する AWS AppSync Merged API ビルドタイムアプローチとルーターベースのランタイムアプローチを比較したものです。


|  |  |  | 
| --- |--- |--- |
| Feature | AppSync Merged API | Router-based solutions | 
| Sub-graphs managed independently | Yes | Yes | 
| Sub-graphs addressable independently | Yes | Yes | 
| Automated schema composition | Yes | Yes | 
| Automated conflict detection | Yes | Yes | 
| Conflict resolution via schema directives | Yes | Yes | 
| Supported sub-graph servers | AWS AppSync\$1 | Varies | 
| Network complexity | Single, merged API means no extra network hops. | Multi-layer architecture requires query planning and delegation, sub-query parsing and serialization/deserialization, and reference resolvers in sub-graphs to perform joins. | 
| Observability support | Built-in monitoring, logging, and tracing. A single, Merged API server means simplified debugging. | Build-your-own observability across router and all associated sub-graph servers. Complex debugging across distributed system. | 
| Authorization support | Built in support for multiple authorization modes. | Build-your-own authorization rules. | 
| Cross account security | Built-in support for cross-AWS cloud account associations. | Build-your-own security model. | 
| Subscriptions support | Yes | No | 

\$1 AWS AppSync マージされた APIsはソース AWS AppSync APIsにのみ関連付けることができます。サブグラフ全体 AWS AppSync およびAWS AppSync サブグラフ以外のスキーマ構成のサポートが必要な場合は、1 つ以上の AWS AppSync GraphQL および/または Merged APIs をルーターベースのソリューションに接続できます。例えば、Apollo Federation v2: [Apollo GraphQL Federation with AWS AppSync](https://aws.amazon.com/blogs/mobile/federation-appsync-subgraph/) を使用したルーターベースのアーキテクチャを使用してサブグラフとして AWS AppSync APIs を追加するためのリファレンスブログを参照してください。

**Topics**
+ [Merged API とフェデレーション](#merged-api-federation)
+ [Merged API の競合の解決](#merged-api-conflict-resolution)
+ [スキーマの設定](#configuring-schemas-merged-api)
+ [承認モードの設定](#configuring-authorization-merged-api)
+ [実行ロールの設定](#execution-roles-merged-api)
+ [を使用したクロスアカウントマージされた APIsの設定 AWS RAM](#cross-account-merged-api)
+ [マージ](#merges)
+ [Merged API に対するその他のサポート](#merge-api-additional-support)
+ [Merged API の制限](#merged-api-limits)
+ [マージされた API に関する考慮事項](#merged-api-considerations)
+ [Merged API の作成](#creating-merged-api)

## Merged API の競合の解決
<a name="merged-api-conflict-resolution"></a>

マージの競合が発生した場合、 は問題のトラブルシューティングに役立ついくつかのツールと例をユーザー AWS AppSync に提供します (複数可）。

### Merged API スキーマのディレクティブ
<a name="merged-api-schema-directive"></a>

 AWS AppSync は、ソース API 間の競合を軽減または解決するために使用できるいくつかの GraphQL ディレクティブを導入しました。 APIs
+ *@canonical*: このディレクティブは、名前とデータが似ている型/フィールドの優先順位を設定します。2 つ以上のソース API が同じ GraphQL タイプまたはフィールドを持つ場合、*いずれかの API がタイプまたはフィールドに標準として注釈を付けることができ*、マージ時に優先順位が付けられます。他のソース API でこのディレクティブでアノテーションが付けられていない競合するタイプ/フィールドは、マージ時に無視されます。
+ *@hidden*: このディレクティブは特定の型/フィールドをカプセル化して、マージプロセスから削除します。チームは、内部クライアントだけが特定の型付きデータにアクセスできるように、ソース API の特定のタイプや操作を削除または非表示にしたい場合があります。このディレクティブをアタッチすると、タイプやフィールドは Merged API にマージされません。
+ *@renamed*: このディレクティブは、名前の競合を減らすためにタイプ/フィールドの名前を変更します。異なる API が同じタイプまたはフィールド名を持つ場合があります。ただし、これらはすべて、マージされたスキーマで使用可能である必要があります。これらすべてを Merged API に含める簡単な方法は、フィールドの名前を似ているが別の名前に変更することです。

ユーティリティスキーマのディレクティブを示すには、次の例を考えます。

この例では、2 つのソース API をマージすると仮定します。投稿 (コメントセクションやソーシャルメディア投稿など) を作成および取得する 2 つのスキーマが与えられます。タイプとフィールドが似ていると、マージ操作中に競合が発生する可能性が高くなります。以下のスニペットは、各スキーマのタイプとフィールドを示しています。

*Source1.graphQL* という名前の最初のファイルは、ユーザーが `putPost` ミューテーションを使用して `Posts` を作成できるようにする GraphQL スキーマです。各 `Post` にはタイトルと ID が含まれています。ID は `User`、または投稿者の情報 (メールと住所)、`Message`、またはペイロード (コンテンツ) を参照するために使用されます。`User` タイプには *@canonical* タグのアノテーションが付けられています。

```
# This snippet represents a file called Source1.graphql

type Mutation {
    putPost(id: ID!, title: String!): Post
}

type Post {
    id: ID!
    title: String!
}

type Message {
   id: ID!
   content: String
}

type User @canonical {
   id: ID!
   email: String!
   address: String!
}

type Query {
    singlePost(id: ID!): Post
    getMessage(id: ID!): Message
}
```

*2 つ目のファイルは *Source2.graphQL* と呼ばれ、*Source1.graphql とよく似た処理を行う GraphQL スキーマです。ただし、各タイプのフィールドは異なることに注意してください。これら 2 つのスキーマをマージすると、これらの違いによりマージによる競合が発生します。

また、*Source2.graphQL* には、これらの競合を減らすためのディレクティブがいくつか含まれていることにも注意してください。`Post` タイプには *@hidden* タグのアノテーションが付いており、マージ操作中にわかりにくくなります。`Message` タイプには *@renamed* タグのアノテーションが付いており、別の `Message` タイプと名前が競合した場合にタイプ名が `ChatMessage` に変更されます。

```
# This snippet represents a file called Source2.graphql

type Post @hidden  {
    id: ID!
    title: String!
    internalSecret: String!
}

type Message @renamed(to: "ChatMessage") {
   id: ID!
   chatId: ID!
   from: User!
   to: User!
}

# Stub user so that we can link the canonical definition from Source1
type User {
   id: ID!
}

type Query {
    getPost(id: ID!): Post
    getMessage(id: ID!): Message @renamed(to: "getChatMessage")
}
```

マージが行われると、結果は `MergedSchema.graphql` ファイルを生成します。

```
# This snippet represents a file called MergedSchema.graphql

type Mutation {
    putPost(id: ID!, title: String!): Post
}

# Post from Source2 was hidden so only uses the Source1 definition. 
type Post {
    id: ID!
    title: String!
}

# Renamed from Message to resolve the conflict
type ChatMessage {
   id: ID!
   chatId: ID!
   from: User!
   to: User!
}

type Message {
   id: ID!
   content: String
}

# Canonical definition from Source1
type User {
   id: ID!
   email: String!
   address: String!
}

type Query {
    singlePost(id: ID!): Post
    getMessage(id: ID!): Message
    
    # Renamed from getMessage
    getChatMessage(id: ID!): ChatMessage
}
```

マージでは次のことが起こりました。
+ *@canonical* アノテーションにより、*Source1.graphql* からの `User` タイプが *Source2.graphql* からの `User` よりも優先されました。
+ *Source1.graphql* からの `Message` タイプがマージに含まれました。ただし、*Source2.graphql* からの `Message` には命名上の競合がありました。その *@renamed* アノテーションにより、代替名 `ChatMessage` でマージに含まれました。
+ *Source1.graphql* から`Post` タイプは含まれていましたが、*Source2.graphql* からの `Post` タイプは含まれていませんでした。通常、このタイプでは競合が発生しますが、*Source2.graphql* からの `Post` タイプには *@hidden* アノテーションが付いていたため、そのデータは難読化され、マージには含まれませんでした。この結果、競合は発生しませんでした。
+ `Query` タイプは両方のファイルの内容を含むように更新されました。ただし、このディレクティブにより、1 つの `GetMessage` クエリの名前が `GetChatMessage` に変更されました。これにより、同じ名前の 2 つのクエリ間の名前の競合が解決されました。

また、競合するタイプにディレクティブが追加されない場合もあります。この場合、マージされたタイプには、そのタイプのすべてのソース定義のすべてのフィールドの和集合が含まれます。例えば、次の例を考えてみます。

このスキーマは *Source1.graphql* と呼ばれ、`Posts` の作成と取得を可能にします。設定は、前述のものと似ていますが、情報が少なくなっています。

```
# This snippet represents a file called Source1.graphql

type Mutation {
    putPost(id: ID!, title: String!): Post
}

type Post  {
    id: ID!
    title: String!
}

type Query {
    getPost(id: ID!): Post
}
```

このスキーマは **Source2.graphql と呼ばれ、`Reviews` (映画の評価やレストランのレビューなど) の作成と取得が可能です。`Reviews` は、同じ ID 値の `Post` と関連付けられています。これらには、レビュー投稿のタイトル、投稿 ID、ペイロードメッセージが含まれます。

マージすると、この 2 つの `Post` タイプが競合することになります。この問題を解決するアノテーションがないため、デフォルトの動作では、競合するタイプに対してユニオンオペレーションを実行します。

```
# This snippet represents a file called Source2.graphql

type Mutation {
    putReview(id: ID!, postId: ID!, comment: String!): Review
}

type Post  {
    id: ID!
    reviews: [Review]
}

type Review {
   id: ID!
   postId: ID!
   comment: String!
}

type Query {
    getReview(id: ID!): Review
}
```

マージが行われると、その結果は `MergedSchema.graphql` ファイルを生成します。

```
# This snippet represents a file called MergedSchema.graphql

type Mutation {
    putReview(id: ID!, postId: ID!, comment: String!): Review
    putPost(id: ID!, title: String!): Post
}

type Post  {
    id: ID!
    title: String!
    reviews: [Review]
}

type Review {
   id: ID!
   postId: ID!
   comment: String!
}

type Query {
    getPost(id: ID!): Post
    getReview(id: ID!): Review
}
```

マージでは次のようなことが起こりました。
+ `Mutation` タイプは競合せず、マージされました。
+ `Post` タイプフィールドはユニオンオペレーションによって結合されました。この 2 つのユニオンによって、単一の `id`、`title`、および単一の `reviews` が生成されることに注目してください。
+ `Review` のタイプは競合せず、マージされました。
+ `Query` のタイプは競合せず、マージされました。

### 共有タイプのリゾルバーの管理
<a name="resolvers-shared-types-merged-api"></a>

上記の例で、**Source1.graphql が `PostDatasource` という名前の DynamoDB データソースを使用する、`Query.getPost` 上のユニットリゾルバーを構成している場合を考えてみましょう。このリゾルバーは `Post` タイプの `id` と `title` を返します。ここで、**Source2.graphql が `Post.reviews` でパイプラインリゾルバーを設定し、2 つの関数を実行しているとします。`Function1` には、カスタムの権限チェックを実行するための `None` データソースがアタッチされています。`Function2` には `reviews` テーブルをクエリするための DynamoDB データソースがアタッチされています。

```
query GetPostQuery {
    getPost(id: "1") {
        id,
        title,
        reviews
    }
}
```

上記のクエリがクライアントによって Merged API エンドポイントに対して実行されると、 AWS AppSync サービスはまず `Query.getPost`から のユニットリゾルバーを実行し`Source1`、 を呼び出し`PostDatasource`て DynamoDB からデータを返します。次に、`Post.reviews` パイプラインリゾルバーを実行し、そこで `Function1` がカスタム認可ロジックを実行して、`Function2` が `$context.source` で見つかった `id` に付与されたレビューを返します。サービスはリクエストを単一の GraphQL 実行として処理し、この単純なリクエストには 1 つのリクエストトークンのみが必要です。

### 共有タイプのリゾルバー競合の管理
<a name="resolver-conflict-shared-type-merged-api"></a>

`Source2` のフィールドリゾルバーを超えて一度に複数のフィールドを提供するために、`Query.getPost` にリゾルバーも実装する場合を考えてみよう。*Source1.graphql* は以下のようになるかもしれません。

```
# This snippet represents a file called Source1.graphql

type Post  {
    id: ID!
    title: String!
    date: AWSDateTime!
}

type Query {
    getPost(id: ID!): Post
}
```

*Source2.graphql* は以下のようになるかもしれません。

```
# This snippet represents a file called Source2.graphql

type Post  {
  id: ID!
  content: String!
  contentHash: String! 
  author: String! 
}

type Query {
    getPost(id: ID!): Post
}
```

Merged APIs では複数のソースリゾルバーを同じフィールドにアタッチできないため、これら 2 つのスキーマをマージしようとすると AWS AppSync マージエラーが発生します。この競合を解決するには、*Source2.graphql* に、`Post` タイプから所有するフィールドを定義する別の型を追加するように要求するフィールドリゾルバーパターンを実装できます。次の例では、`PostInfo` というタイプを追加します。このタイプには、*Source2.graphql* によって解決されるコンテンツフィールドと作成者フィールドが含まれます。*Source1.graphql* は `Query.getPost` にアタッチされたリゾルバーを実装し、*Source2.graphQL* はすべてのデータを正常に取得できるようにリゾルバーを `Post.postInfo` にアタッチします。

```
type Post  {
  id: ID!
  postInfo: PostInfo
}

type PostInfo {
   content: String!
   contentHash: String!
   author: String!
}

type Query {
    getPost(id: ID!): Post
}
```

このような競合を解決するには、ソース API スキーマを書き直す必要があり、場合によってはクライアントがクエリを変更する必要がありますが、このアプローチの利点は、マージされたリゾルバーの所有権がソースチーム間で明確になることです。

## スキーマの設定
<a name="configuring-schemas-merged-api"></a>

Merged API を作成するためのスキーマの設定は、次の 2 つの関係者が担当します。
+ **Merged API 所有者** - Merged API 所有者は、Merged API の承認ロジックと、ロギング、トレーシング、キャッシュ、WAF サポートなどの詳細設定を構成する必要があります。
+ **関連ソース API 所有者** - 関連 API 所有者は、Merged API を構成するスキーマ、リゾルバー、データソースを設定する必要があります。

Merged API のスキーマは関連するソース API のスキーマから作成されるため、**読み取り専用**です。つまり、スキーマの変更はソース API で開始する必要があります。 AWS AppSync コンソールでは、スキーマウィンドウの上にあるドロップダウンリストを使用して、Merged APIs スキーマと Merged API に含まれるソース API の個々の**スキーマ**を切り替えることができます。

## 承認モードの設定
<a name="configuring-authorization-merged-api"></a>

Merged API を保護するために複数の承認モードを使用できます。の認可モードの詳細については AWS AppSync、[「認可と認証](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html)」を参照してください。

Merged API では以下の承認モードを使用できます。
+  **API キー**: 最も単純な商人戦略。すべてのリクエストには、`x-api-key` リクエストヘッダーの下に API キーを含める必要があります。期限切れの API キーは、有効期限後 60 日間保管されます。
+  **AWS Identity and Access Management (IAM)**: AWS IAM 認可戦略は、**sigv4 で署名**されたすべてのリクエストを承認します。
+  **Amazon Cognito ユーザープール**: Amazon Cognito ユーザープールを使用してユーザーを承認すると、よりきめ細かい制御が可能になります。
+  **AWS Lambda Authorizer**: カスタムロジックを使用して AWS AppSync API へのアクセスを認証および認可できるサーバーレス関数。
+ **OpenID Connect**: この認可タイプは、OIDC 準拠サービスによって提供される OpenID Connect (OIDC) トークンを適用します。アプリケーションは、アクセス制御に対して、使用する OIDC プロバイダーによって定義されたユーザーと権限を活用できます。

Merged API の承認モードは、統合された API の所有者によって設定されます。マージ操作時に、Merged API には、ソース API に設定されたプライマリ認可モードを、独自のプライマリ認可モードまたはセカンダリ認可モードとして含める必要があります。そうしないと、互換性がなくなり、マージオペレーションは競合が発生して失敗します。ソース API でマルチ認証ディレクティブを使用すると、マージプロセスでこれらのディレクティブを統合エンドポイントに自動的にマージできます。ソース API のプライマリ承認モードがMerged API のプライマリ承認モードと一致しない場合、ソース API のタイプの承認モードの一貫性が保たれるように、これらの承認ディレクティブが自動的に追加されます。

## 実行ロールの設定
<a name="execution-roles-merged-api"></a>

Merged API を作成するときは、サービスロールを定義する必要があります。 AWS サービスロールは、ユーザーに代わってタスクを実行するために AWS サービスで使用される AWS Identity and Access Management (IAM) ロールです。

この場合、Merged API は、ソース API に設定されたデータソースのデータにアクセスするリゾルバーを実行する必要があります。そのために必要なサービスロールは `mergedApiExecutionRole` であり、`appsync:SourceGraphQL` IAM アクセス許可を介してマージされた API に含まれるソース API のリクエストを実行するための明示的なアクセス権が必要です。GraphQL リクエストの実行中に、 AWS AppSync サービスはこのサービスロールを引き受け、`appsync:SourceGraphQL`アクションを実行するロールを承認します。

AWS AppSync では、IAM APIs。最non-top-levelフィールドの場合、 ではソース API ARN 自体に対するアクセス許可を定義 AWS AppSync する必要があります。Merged API の特定の非トップレベルフィールドへのアクセスを制限するには、Lambda 内にカスタムロジックを実装するか、*@hidden* ディレクティブを使用してソース API フィールドを Merged API から非表示にすることをお勧めします。ソース API 内のすべてのデータ操作をロールに実行させたい場合は、以下のポリシーを追加できます。最初のリソースエントリはすべての最上位フィールドへのアクセスを許可し、2 番目のエントリはソース API リソース自体を認可する子リゾルバーを対象としていることに注意してください。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [{
        "Effect": "Allow", 
        "Action": [ "appsync:SourceGraphQL"], 
        "Resource": [ 
            "arn:aws:appsync:us-west-2:123456789012:apis/YourSourceGraphQLApiId/*", 
            "arn:aws:appsync:us-west-2:123456789012:apis/YourSourceGraphQLApiId"] 
    }] 
}
```

------

アクセスを特定の最上位フィールドのみに制限したい場合は、次のようなポリシーを使用できます。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [{
        "Effect": "Allow", 
        "Action": [ "appsync:SourceGraphQL"], 
        "Resource": [ 
            "arn:aws:appsync:us-west-2:123456789012:apis/YourSourceGraphQLApiId/types/Query/fields/<Field-1>",
            "arn:aws:appsync:us-west-2:123456789012:apis/YourSourceGraphQLApiId"] 
    }] 
}
```

------

 AWS AppSync コンソール API 作成ウィザードを使用してサービスロールを生成し、マージされた API がマージされた API と同じアカウントにあるソース APIs で設定されたリソースにアクセスすることを許可することもできます。ソース APIs がマージされた API と同じアカウントにない場合は、まず Resource Access Manager () を使用して AWS リソースを共有する必要がありますAWS RAM。

## を使用したクロスアカウントマージされた APIsの設定 AWS RAM
<a name="cross-account-merged-api"></a>

Merged API を作成するときは、オプションで、 AWS Resource Access Manager () を介して共有されている他のアカウントのソース APIs を関連付けることができますAWS RAM。 AWS RAM を使用すると、 AWS アカウント間、組織内または組織単位 (OUs)、IAM ロールとユーザーとリソースを安全に共有できます。

AWS AppSync は と統合 AWS RAM して、単一の Merged APIs から複数のアカウントにわたるソース API の設定とアクセスをサポートします。 AWS RAM では、リソース共有、またはリソースのコンテナ、およびリソースごとに共有されるアクセス許可セットを作成できます。リソース共有 AWS AppSync APIs を追加できます AWS RAM。リソース共有内で、 AWS AppSync は RAM の AWS AppSync API に関連付けることができる 3 つの異なるアクセス許可セットを提供します。

1. `AWSRAMPermissionAppSyncSourceApiOperationAccess`: 他のアクセス許可が指定され AWS RAM ていない場合に で AWS AppSync API を共有するときに追加されるデフォルトのアクセス許可セット。このアクセス許可セットは、ソース AWS AppSync API を Merged API 所有者と共有するために使用されます。このアクセス許可には、ソース API `appsync:AssociateMergedGraphqlApi` に対する権限と、ランタイムにソース API リソースにアクセスするために必要な `appsync:SourceGraphQL` アクセス許可が含まれます。

1. `AWSRAMPermissionAppSyncMergedApiOperationAccess`: このアクセス許可セットは、Merged API をソース API 所有者と共有する場合に設定する必要があります。このアクセス許可セットにより、ソース API は Merged API を設定できるようになります。これには、ターゲットプリンシパルが所有するソース API を Merged API に関連付ける機能や、Merged API のソース API 関連付けを読み取って更新する機能が含まれます。

1. `AWSRAMPermissionAppSyncAllowSourceGraphQLAccess`: このアクセス許可セットでは、 AWS AppSync API でアクセス`appsync:SourceGraphQL`許可を使用できます。これは、ソース API を Merged API の所有者と共有するためのものです。ソース API 操作アクセス用のデフォルトの権限セットとは対照的に、この権限セットにはランライムアクセス許可 `appsync:SourceGraphQL` のみが含まれます。Merged API オペレーションへのアクセス権をソース API 所有者と共有することを選択した場合、Merged API エンドポイントを通じてランタイムアクセスできるようにするには、ソース API からのこの権限を Merged API 所有者にも共有する必要があります。

AWS AppSync は、カスタマー管理のアクセス許可もサポートしています。提供された AWS管理アクセス許可の 1 つが機能しない場合は、独自のカスタマー管理アクセス許可を作成できます。カスタマー管理アクセス許可は、 を使用して共有されたリソースで実行できる条件を正確に指定することで、作成および維持する管理アクセス許可です AWS RAM。 AWS AppSync では、独自のアクセス許可を作成するときに、次のアクションから選択できます。

1. `appsync:AssociateSourceGraphqlApi`

1. `appsync:AssociateMergedGraphqlApi`

1. `appsync:GetSourceApiAssociation`

1. `appsync:UpdateSourceApiAssociation`

1. `appsync:StartSchemaMerge`

1. `appsync:ListTypesByAssociation`

1. `appsync:SourceGraphQL`

でソース API または Merged API を適切に共有 AWS RAM し、必要に応じてリソース共有の招待が承認されると、Merged API でソース API の関連付けを作成または更新するときに AWS AppSync コンソールに表示されます。によって提供される`ListGraphqlApis`オペレーションを呼び出し、`OTHER_ACCOUNTS`所有者フィルターを使用して、アクセス許可セットに関係なく AWS AppSync 、 を使用してアカウント AWS RAM と共有されたすべての AWS AppSync APIs を一覧表示することもできます。

**注記**  
経由で共有する AWS RAM には、 の呼び出し元 AWS RAM に、共有されている API に対して`appsync:PutResourcePolicy`アクションを実行するアクセス許可が必要です。

## マージ
<a name="merges"></a>

### マージの管理
<a name="managing-merges"></a>

Merged APIsは、統合 AWS AppSync エンドポイントでのチームコラボレーションをサポートすることを目的としています。チームがバックエンドで独自の独立したソース GraphQL API を独自に進化させながら、 AWS AppSync サービスが単一の Merged API エンドポイントへのリソースの統合を管理することで、コラボレーションにおける摩擦を減らし、開発リードタイムを短縮できます。

### 自動マージ
<a name="auto-merge"></a>

 AWS AppSync Merged APIs に関連付けられたソース API は、ソース API に変更を加えた後に Merged API に自動的にマージ (自動マージ) するように設定できます。これにより、ソース API からの変更が常にバックグラウンドで Merged API エンドポイントに反映されます。ソース API スキーマの変更は、Merged API の既存の定義とのマージによる競合が発生しない限り、Merged API でも更新されます。ソース API の更新によってリゾルバー、データソース、または関数を更新する場合、インポートされたリソースも更新されます。自動的に解決 (自動解決) できない新しい競合が発生すると、マージ操作中にサポートされていないコンフリクトが発生したため、Merged API スキーマの更新は拒否されます。エラーメッセージは、ステータスが `MERGE_FAILED` の各ソース API アソシエーションのコンソールに表示されます。 AWS SDK を使用するか、次のように CLI を使用して、特定のソース API 関連付けの AWS `GetSourceApiAssociation`オペレーションを呼び出すことで、エラーメッセージを調べることもできます。

```
aws appsync get-source-api-association --merged-api-identifier <Merged API ARN> --association-id <SourceApiAssociation id>
```

これにより、次の形式で結果が生成されます。

```
{
    "sourceApiAssociation": {
        "associationId": "<association id>",
        "associationArn": "<association arn>",
        "sourceApiId": "<source api id>",
        "sourceApiArn": "<source api arn>",
        "mergedApiArn": "<merged api arn>",
        "mergedApiId": "<merged api id>",
        "sourceApiAssociationConfig": {
            "mergeType": "MANUAL_MERGE"
        },
        "sourceApiAssociationStatus": "MERGE_FAILED",
        "sourceApiAssociationStatusDetail": "Unable to resolve conflict on object with name title: Merging is not supported for fields with different types."
    }
}
```

### 手動マージ
<a name="manual-merges"></a>

ソース API のデフォルト設定は手動マージです。Merged APIs が最後に更新されてからソース API で発生した変更をマージするには、ソース API 所有者は AWS AppSync コンソールから、または AWS SDK と AWS CLI で利用可能な`StartSchemaMerge`オペレーションを介して手動マージを呼び出すことができます。

## Merged API に対するその他のサポート
<a name="merge-api-additional-support"></a>

### サブスクリプションの設定
<a name="config-subscription"></a>

GraphQL スキーマ構成に対するルーターベースのアプローチとは異なり、 AWS AppSync マージされた APIsは GraphQL サブスクリプションの組み込みサポートを提供します。関連するソース API で定義されたすべてのサブスクリプション操作は、変更なしでMerged API に自動的にマージされて機能します。がサーバーレス WebSockets 接続を介してサブスクリプション AWS AppSync をサポートする方法の詳細については、[「リアルタイムデータ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html)」を参照してください。 WebSockets 

### オブザーバビリティの設定
<a name="config-observability"></a>

AWS AppSync Merged APIsは、[Amazon CloudWatch](https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html) を介して組み込みのログ記録、モニタリング、メトリクスを提供します。 AWS AppSync また、 を介してトレースするための組み込みサポートも提供します[AWS X-Ray](https://docs.aws.amazon.com/appsync/latest/devguide/x-ray-tracing.html)。

### カスタムドメインの設定
<a name="config-custom-domain"></a>

AWS AppSync Merged APIsは、Merged API の [GraphQL およびリアルタイムエンドポイント](https://docs.aws.amazon.com/appsync/latest/devguide/custom-domain-name.html)でカスタムドメインを使用するための組み込みサポートを提供します。

### キャッシュの設定
<a name="config-caching"></a>

AWS AppSync Merged APIsは、オプションでリクエストレベルやリゾルバーレベルのレスポンスのキャッシュとレスポンスの圧縮を組み込みでサポートします。詳細については、「[キャッシュと圧縮](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html)」を参照してください。

### プライベート API の設定
<a name="config-private-api"></a>

AWS AppSync Merged APIsは、Merged APIs の GraphQL エンドポイントとリアルタイムエンドポイントへのアクセスを[、設定可能な VPC エンドポイント](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html)から発信されるトラフィックに制限するプライベート API の組み込みサポートを提供します。

### ファイアウォールルールの設定
<a name="config-firewall"></a>

AWS AppSync Merged APIsは の組み込みサポートを提供するため AWS WAF、[ウェブアプリケーションのファイアウォールルール](https://docs.aws.amazon.com/appsync/latest/devguide/WAF-Integration.html)を定義して APIsを保護できます。

### 監査ログ記録の設定
<a name="config-audit"></a>

AWS AppSync Merged APIsは AWS CloudTrail の組み込みサポートを提供するため、[監査ログを設定および管理](https://docs.aws.amazon.com/appsync/latest/devguide/cloudtrail-logging.html)できます。

## Merged API の制限
<a name="merged-api-limits"></a>

マージド API を開発するときは、以下のルールに注意してください。

1. Merged API を別の Merged API のソース API にすることはできません。

1. ソース API を複数の Merged API に関連付けることはできません。

1. Merged API スキーマドキュメントのデフォルトのサイズ制限は 10 MB です。

1. Merged API に関連付けることができるソース API のデフォルト数は 10 です。ただし、マージド API に 10 個を超えるソース API が必要な場合は、制限の引き上げをリクエストできます。

## マージされた API に関する考慮事項
<a name="merged-api-considerations"></a>

Merged APIsを設計および実装する場合は、次の点を考慮してください。

複数のソース APIs 1 つのエンドポイントにマージすると、GraphQL スキーマとクエリのサイズと複雑さが増す可能性があります。マージされたスキーマが大きくなるにつれて、クエリは 1 つのリクエストを満たすために複数のリゾルバーをトラバースする必要がある場合があります。これにより、全体的なリクエスト時間にレイテンシーが生じる可能性があります。たとえば、複数のソース APIs からフィールドにアクセスするクエリでは、各ソース API からリゾルバーを順番に実行 AWS AppSync し、各リゾルバーが合計応答時間に追加する必要がある場合があります。

Merged APIs は、ビジネス要件を満たしていることを確認するために、開発中および現実的な負荷条件下で徹底的にテストすることを強くお勧めします。以下の点に特に注意してください。
+ マージされたスキーマの深さと複雑さ、特に複数のソース APIs のフィールドにアクセスするクエリ。
+ 一般的なクエリパターンを満たすために実行する必要があるリゾルバーの数。
+ 予想される負荷におけるデータソースとリゾルバーのパフォーマンス特性。
+ 複数のソース APIs でリソースにアクセスする場合のネットワークレイテンシーの影響。

キャッシュ、データソースリクエストのバッチ処理、ソース API スキーマの設計などのパフォーマンス最適化を実装して、一般的なオペレーションに必要なリゾルバー実行の数を最小限に抑えることを検討してください。

## Merged API の作成
<a name="creating-merged-api"></a>

**コンソールで Merged API を作成するには**

1. にサインイン AWS マネジメントコンソール し、 [AWS AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **ダッシュボード**で、**[API の作成]** を選択します。

1. **[Merged API]** を選択し、**[次へ]** を選択します。

1. **[API の詳細を指定]** ページで、次の情報を入力します。

   1. **[認証情報]** で以下の情報を入力します。

      1. マージド API の **API 名**を指定します。このフィールドは、他の GraphQL API と簡単に区別できるように、GraphQL API にラベルを付ける方法です。

      1. **連絡先の詳細**を指定してください。このフィールドはオプションで、GraphQL API に名前またはグループをアタッチします。他のリソースにリンクされたり生成されたりすることはなく、API 名フィールドとほとんど同じように機能します。

   1. **サービスロール**では、 が実行時にリソース AWS AppSync を安全にインポートして使用できるように、マージされた API に IAM 実行ロールをアタッチする必要があります。**新しいサービスロールを作成して使用**することもできます。これにより、 AWS AppSync が使用するポリシーとリソースを指定できます。**[既存のサービスロールを使用する]** を選択し、ドロップダウンリストからロールを選択することで、既存の IAM ロールをインポートすることもできます。

   1. **[プライベート API 設定]** では、プライベート API 機能を有効にすることを選択できます。マージド API を作成した後では、この選択を変更できないことに注意してください。プライベート API についての詳細は、「[AWS AppSync プライベート API の使用](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html)」を参照してください。

      終了したら、**[次へ]** を選択します。

1. 次に、マージド API の基盤として使用される GraphQL API を追加する必要があります。**[ソース API の選択]** ページで、以下の情報を入力します。

   1. ** AWS アカウントテーブルAPIs で**、**ソース APIs の追加** を選択します。GraphQL API のリストでは、各エントリには次のデータが含まれます。

      1. **名前**: GraphQL API の **API 名**フィールド。

      1. **API ID**: GraphQL API の一意の ID 値。

      1. **プライマリ承認モード**: GraphQL API のデフォルト承認モード。 AWS AppSyncでの認可モードについての詳細は、「[認可と認証](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html)」を参照してください。

      1. **追加認可モード**: GraphQL API で設定されていたセカンダリ認可モード。

      1. API の**名前**フィールドの横にあるチェックボックスを選択して、マージド API で使用する API を選択します。次に、**[ソース API を追加]** を選択します。選択した GraphQL API は、** AWS アカウントテーブルの API** テーブルに表示されます。

   1. **他の AWS アカウントの APIs**で、**ソース APIs の追加**を選択します。このリストの GraphQL APIs は、 AWS Resource Access Manager () を通じてリソースを共有している他のアカウントから取得されますAWS RAM。この表の GraphQL API を選択するプロセスは、前のセクションのプロセスと同じです。を通じてリソースを共有する方法の詳細については AWS RAM、[「 とは AWS Resource Access Manager](https://docs.aws.amazon.com/ram/latest/userguide/what-is.html)」を参照してください。

      終了したら、**[次へ]** を選択します。

   1. プライマリ承認モードを追加します。詳細については、「[認可と認証](https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html)」を参照してください。**[次へ]** をクリックします。

   1. 入力内容を確認し、**[API を作成]** を選択します。

# RDS イントロスペクションを使用した GraphQL API の構築
<a name="rds-introspection"></a>

AWS AppSyncのイントロスペクションユーティリティは、データベーステーブルからモデルを検出し、GraphQL の型を提案できます。 AWS AppSync コンソールの API 作成ウィザードは、Aurora MySQL または PostgreSQL データベースから API を即座に生成できます。データを読み書きするための型と JavaScript リゾルバーを自動的に作成されます。

AWS AppSync は、Amazon RDS Data API を介して Amazon Aurora データベースと直接統合します。Amazon RDS Data API は、永続的なデータベース接続を必要とするのではなく、SQLステートメントを実行するために AWS AppSync に接続する安全な HTTP エンドポイントを提供します。これを使用して、Aurora で MySQL および PostgreSQL ワークロードのリレーショナルデータベース API を作成できます。

を使用してリレーショナルデータベース用の API を構築する AWS AppSync と、いくつかの利点があります。
+ データベースはクライアントに直接公開されないため、アクセスポイントをデータベース自体から切り離すことができます。
+ さまざまなアプリケーションのニーズに合わせた専用の API を構築できるため、フロントエンドでのカスタムビジネスロジックが不要になります。これは Backend For Frontend (BFF) パターンと一致します。
+ 認可とアクセスコントロールは、アクセスを制御するためにさまざまな認可モードを使用して AWS AppSync レイヤーに実装できます。データベースに接続するために、ウェブサーバーのホスティングやプロキシ接続など、追加のコンピューティングリソースは必要ありません。
+ リアルタイム機能はサブスクリプションを通じて追加でき、AppSync を介して行われたデータミューテーションは、接続されたクライアントに自動的にプッシュされます。
+ クライアントは 443 などの共通ポートを使用して HTTPS 経由で API に接続できます。

AWS AppSync を使用すると、既存のリレーショナルデータベースから APIs を簡単に構築できます。そのイントロスペクションユーティリティは、データベーステーブルからモデルを検出し、GraphQL の型を提案できます。 AWS AppSync コンソールの **API 作成ウィザードを使用すると、Aurora MySQL または PostgreSQL データベースから API を即座に生成できます。データを読み書きするための型と JavaScript リゾルバーを自動的に作成されます。

AWS AppSync には、リゾルバーでの SQL ステートメントの記述を簡素化する統合 JavaScript ユーティリティが用意されています。動的値を持つ静的ステートメントに AWS AppSyncの`sql`タグテンプレートを使用するか、`rds`モジュールユーティリティを使用してプログラムでステートメントを構築できます。詳細については、「[RDS のリゾルバー関数リファレンス](https://docs.aws.amazon.com//appsync/latest/devguide/resolver-reference-rds-js.html)」データソースと「[組み込みモジュール](https://docs.aws.amazon.com//appsync/latest/devguide/built-in-modules-js.html#built-in-rds-modules)」をご覧ください。

## イントロスペクション機能を使用する (コンソール)
<a name="using-introspection-console"></a>

詳細なチュートリアルと入門ガイドについては、「[チュートリアル: Aurora PostgreSQL Serverless で Data API を使用する](https://docs.aws.amazon.com//appsync/latest/devguide/aurora-serverless-tutorial-js.html)」を参照してください。

 AWS AppSync コンソールを使用すると、Data API で設定された既存の Aurora データベースから AWS AppSync GraphQL API をわずか数分で作成できます。これにより、データベース設定に基づいて運用スキーマが迅速に生成されます。API をそのまま使用することも、API を基にして機能を追加することもできます。

1. にサインイン AWS マネジメントコンソール し、[AppSync コンソール](https://console.aws.amazon.com/appsync/)を開きます。

   1. **ダッシュボード**で、**[API の作成]** を選択します。

1. **[API のオプション]** で、**[GraphQL API]**、**[Amazon Aurora クラスターから始める]**、**[次へ]** の順に選択します。

   1. **[API 名]** を入力します。これはコンソールで API の識別子として使用されます。

   1. **連絡先情報**については、API のマネージャーを特定する連絡先を入力できます。これはオプションのフィールドです。

   1. **[Private API 設定]** で、プライベート API 機能を有効にできます。プライベート API には、設定された VPC エンドポイント (VPCE) からのみアクセスできます。詳細については、「[プライベート DNS](https://docs.aws.amazon.com//appsync/latest/devguide/using-private-apis.html)」を参照してください。

      この例では、この機能を有効にすることはお勧めしません。**[次へ]** 選択して入力を確認します。

1. **[データベース]** ページで **[データベースを選択]** を選択します。

   1. クラスターからデータベースを選択する必要があります。最初のステップは、クラスターが存在する **[リージョン]** を選択することです。

   1. ドロップダウンリストから **[Aurora クラスター]** を選択します。リソースを使用する前に、対応するData API を作成して[有効](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/data-api.html#data-api.enabling)にしておく必要があることに注意してください。

   1. 次に、データベースの認証情報をサービスに追加する必要があります。これは主に を使用して行われます AWS Secrets Manager。シークレットが存在する **[リージョン]** を選択します。シークレット情報を取得する方法の詳細については、「[シークレットを検索する](https://docs.aws.amazon.com//secretsmanager/latest/userguide/manage_search-secret.html)」または「[シークレットの取得](https://docs.aws.amazon.com//secretsmanager/latest/userguide/retrieving-secrets.html)」を参照してください。

   1. ドロップダウンリストからシークレットを選択します。ユーザーにはデータベースの[読み取りアクセス許可](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-console)が必要であることに注意してください。

1. [**インポート**] を選択します。

   AWS AppSync は、データベースのイントロスペクション、テーブル、列、プライマリキー、インデックスの検出を開始します。検出されたテーブルが GraphQL API でサポートされるかどうかをチェックします。新しい行の作成をサポートするには、テーブルにプライマリキーが必要です。プライマリキーでは、次のように複数の columns. AWS AppSync maps テーブル列を使用してフィールドを入力できます。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/rds-introspection.html)

1. テーブルの検出が完了すると、**[データベース]** セクションに情報が入力されます。新しい **[データベーステーブル]** セクションでは、テーブルからのデータがすでに入力され、スキーマの型に変換されている場合があります。必要なデータの一部が表示されない場合は、**[テーブルを追加]** を選択し、表示されるモーダルでそれらの型のチェックボックスをクリックして、**[追加]** を選択することで確認できます。

   **[データベーステーブル]** セクションから型を削除するには、削除する型の横にあるチェックボックスをクリックし、**[削除]** を選択します。削除した型は、後で再度追加したい場合、**[テーブルを追加]** モーダルに表示されます。

    AWS AppSync はテーブル名をタイプ名として使用しますが、名前は変更できます。たとえば、*movies* などの複数のテーブル名をタイプ名 *Movie* に変更します。**[データベーステーブル]** セクションで型名を変更するには、名前を変更する型のチェックボックスをクリックし、**[タイプ名]** 列の**鉛筆アイコンをクリックします。

   選択内容に基づいてスキーマの内容をプレビューするには、**[スキーマをプレビュー]** を選択します。このスキーマは空にはできないため、少なくとも 1 つのテーブルを型に変換する必要があることに注意してください。また、このスキーマのサイズは 1 MB を超えることはできません。

   1. **[サービスロール]** で、このインポート専用の新しいサービスロールを作成するか、既存のロールを使用するかを選択します。

1. [**次へ**] を選択します。

1. 次に、読み取り専用 API (クエリのみ) を作成するか、データの読み取りと書き込み用の API (クエリとミューテーションを含む) を作成するかを選択します。後者は、ミューテーションによってトリガーされるリアルタイムサブスクリプションもサポートします。

1. [**次へ**] を選択します。

1. 選択内容を確認し、**[API を作成]** を選択します。 AWS AppSync は API を作成し、クエリとミューテーションにリゾルバーをアタッチします。生成された API は完全に動作し、必要に応じて拡張できます。

## イントロスペクション機能の使用 (API)
<a name="using-introspection-api"></a>

`StartDataSourceIntrospection` イントロスペクション API を使用して、データベース内のモデルをプログラムで検出できます。コマンドの詳細については、「[https://docs.aws.amazon.com//appsync/latest/APIReference/API_StartDataSourceIntrospection.html](https://docs.aws.amazon.com//appsync/latest/APIReference/API_StartDataSourceIntrospection.html) API の使用」を参照してください。

を使用するには`StartDataSourceIntrospection`、Aurora クラスターの Amazon リソースネーム (ARN)、データベース名、シー AWS Secrets Manager クレット ARN を指定します。このコマンドはイントロスペクションプロセスを開始します。`GetDataSourceIntrospection` コマンドを使用して結果を取得できます。検出されたモデルのストレージ定義言語 (SDL) 文字列をコマンドが返すかどうかを指定できます。これは、検出されたモデルから直接 SDL スキーマ定義を生成する場合に便利です。

 例えば、単純な `Todos` テーブルに次のようなデータ定義言語 (DDL) ステートメントがあるとします。

```
create table if not exists public.todos  
(  
id serial constraint todos_pk primary key,  
description text,  
due timestamp,  
"createdAt" timestamp default now()  
);
```

イントロスペクションは、以下のように開始します。

```
aws appsync start-data-source-introspection \ 
  --rds-data-api-config resourceArn=<cluster-arn>,secretArn=<secret-arn>,databaseName=database
```

次に、`GetDataSourceIntrospection` コマンドを使用して結果を取得します。

```
aws appsync get-data-source-introspection \
  --introspection-id a1234567-8910-abcd-efgh-identifier \
  --include-models-sdl
```

これは次の結果を返します。

```
{
    "introspectionId": "a1234567-8910-abcd-efgh-identifier",
    "introspectionStatus": "SUCCESS",
    "introspectionStatusDetail": null,
    "introspectionResult": {
        "models": [
            {
                "name": "todos",
                "fields": [
                    {
                        "name": "description",
                        "type": {
                            "kind": "Scalar",
                            "name": "String",
                            "type": null,
                            "values": null
                        },
                        "length": 0
                    },
                    {
                        "name": "due",
                        "type": {
                            "kind": "Scalar",
                            "name": "AWSDateTime",
                            "type": null,
                            "values": null
                        },
                        "length": 0
                    },
                    {
                        "name": "id",
                        "type": {
                            "kind": "NonNull",
                            "name": null,
                            "type": {
                                "kind": "Scalar",
                                "name": "Int",
                                "type": null,
                                "values": null
                            },
                            "values": null
                        },
                        "length": 0
                    },
                    {
                        "name": "createdAt",
                        "type": {
                            "kind": "Scalar",
                            "name": "AWSDateTime",
                            "type": null,
                            "values": null
                        },
                        "length": 0
                    }
                ],
                "primaryKey": {
                    "name": "PRIMARY_KEY",
                    "fields": [
                        "id"
                    ]
                },
                "indexes": [],
                "sdl": "type todos\n{\ndescription: String\n\ndue: AWSDateTime\n\nid: Int!\n\ncreatedAt: AW
SDateTime\n}\n"
            }
        ],
        "nextToken": null
    }
}
```