GraphQL API リゾルバーを JavaScript により記述する AWS AppSync Samples が提供されていたので試してみた

2023.08.26

こんにちは、CX事業本部 Delivery部の若槻です。

最近の AWS AppSync のアップデートで、すべての種類の GraphQL API リゾルバーで JavaScript がサポートされました。

これにより、開発者はリゾルバー内で Velocity Template Language (VTL) 関数ではなく、慣れ親しんだ言語で変換処理の記述が可能になりました。

今回は、GraphQL API リゾルバーを JavaScript により記述する AWS AppSync Samples が提供されていたので試してみました。

試してみた

Git Clone

AWS AppSync Samples リポジトリをクローンします。

git clone https://github.com/aws-samples/aws-appsync-resolver-samples.git

ディレクトリ構成は下記のようになります。

$ tree -L 4
.
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── appsync-logo-600.png
├── examples
│   ├── cdk
│   │   ├── aoss-search-app
│   │   │   (略)
│   │   ├── constructs
│   │   │   └── appsync-helper
│   │   ├── dynamodb-todo-app
│   │   │   ├── README.md
│   │   │   ├── bin
│   │   │   ├── cdk.json
│   │   │   ├── cdk.out
│   │   │   ├── jest.config.js
│   │   │   ├── lib
│   │   │   ├── package-lock.json
│   │   │   ├── package.json
│   │   │   ├── test
│   │   │   └── tsconfig.json
│   │   └── pub-sub-app
│   │       (略)
│   └── cloudformation
│       (略)
├── package-lock.json
├── package.json
├── samples
│   (略)
└── scripts
    (略)

37 directories, 62 files

今回はexamples/cdk/dynamodb-todo-appにある CDK プロジェクトを試してみます。

依存関係のインストール

AppSyncHelper

npm run init --prefix examples/cdk/constructs/appsync-helper

AppSyncHelper は AWS AppSync API を作成するためのユーティリティクラスです。後述の DynamoDB Todo App でこのクラスを使用し、スキーマファイルの定義と AWS AppSync API に必要なリゾルバーの作成を簡略化しています。

DynamoDB Todo App

npm install --prefix examples/cdk/dynamodb-todo-app

DynamoDB Todo App は、AWS AppSync API と DynamoDB テーブルを作成する CDK プロジェクトです。

型をスキーマファイルから生成

examples/cdk/dynamodb-todo-app/lib/appsync/schema.graphql から型を生成します。

npm run codegen --prefix examples/cdk/dynamodb-todo-app

この npm script の実体は amplify codegen コマンドです。

これにより examples/cdk/dynamodb-todo-app/lib/appsync/resolvers にあるリゾルバーで使用される型定義が生成されます。

例えば、Query.getTodo.ts は下記のようになります。CreateTodoMutationVariablesがインポートされて使用されています。

examples/cdk/dynamodb-todo-app/lib/appsync/resolvers/Query.getTodo.ts

import { util, Context } from '@aws-appsync/utils';
import { CreateTodoMutationVariables } from '../codegen';
import { dynamodbPutRequest } from './utils';
export { checkErrorsAndRespond as response } from './utils';

export function request(ctx: Context<CreateTodoMutationVariables>) {
	const { input: values } = ctx.arguments;
	const key = { id: util.autoId() };
	const condition = { id: { attributeExists: false } };
	console.log('--> create todo with requested values: ', values);
	return dynamodbPutRequest({ key, values, condition });
}

この別途生成した型定義のインポートはリゾルバーを JavaScript で記述しているからこそ可能になっています。型に変更があった場合は再度型定義の生成が必要となります。

デプロイ

npm run cdk deploy --prefix examples/cdk/dynamodb-todo-app

動作確認

コンソールからクエリを実行してみます。AWS AppSync では簡単にクエリを実行できる Explorer が提供されています。

CreateTodo

CreateTodo クエリを実行してデータを作成します。id は自動生成されます。

mutation CreateTodo {
  createTodo(input: {
    title: "My first todo",
    description: "This is my first todo item",
    owner: "John Doe"
  }) {
    id
    title
    description
    owner
  }
}

データが作成できました。

{
  "data": {
    "createTodo": {
      "id": "5022aa80-278f-4b78-88e8-cb4f36717be9",
      "title": "My first todo",
      "description": "This is my first todo item",
      "owner": "John Doe"
    }
  }
}

ちなみに id の値は前述のQuery.getTodo.tsの通り、util.autoId()により自動生成されています。この util は npm ライブラリである@aws-appsync/utilsからインポートされています。

GetTodo

GetTodo クエリを実行して id 指定でデータを取得します。

query GetTodo {
  getTodo(id: "5022aa80-278f-4b78-88e8-cb4f36717be9") {
    id
    title
    description
    owner
  }
}

指定した id のデータが取得できました。

{
  "data": {
    "getTodo": {
      "id": "5022aa80-278f-4b78-88e8-cb4f36717be9",
      "title": "My first todo",
      "description": "This is my first todo item",
      "owner": "John Doe"
    }
  }
}

ListTodos

ListTodos クエリを実行してデータのリストを取得します。

query ListTodos {
  listTodos(limit: 10) {
    items {
      id
      title
      description
      owner
    }
    nextToken
  }
}

データのリストが取得できました。

{
  "data": {
    "listTodos": {
      "items": [
        {
          "id": "5022aa80-278f-4b78-88e8-cb4f36717be9",
          "title": "My first todo",
          "description": "This is my first todo item",
          "owner": "John Doe"
        }
      ],
      "nextToken": null
    }
  }
}

UpdateTodo

UpdateTodo クエリを実行してデータを更新します。

mutation UpdateTodo {
  updateTodo(input: {
    id: "5022aa80-278f-4b78-88e8-cb4f36717be9",
    title: "My updated todo",
    description: "This is my updated todo item",
    owner: "Jane Doe"
  }) {
    id
    title
    description
    owner
  }
}

データが更新できました。

{
  "data": {
    "updateTodo": {
      "id": "5022aa80-278f-4b78-88e8-cb4f36717be9",
      "title": "My updated todo",
      "description": "This is my updated todo item",
      "owner": "Jane Doe"
    }
  }
}

DeleteTodo

DeleteTodo クエリを実行してデータを削除します。

mutation DeleteTodo {
  deleteTodo(input: {
    id: "5022aa80-278f-4b78-88e8-cb4f36717be9"
  }) {
    id
    title
    description
    owner
  }
}

データが削除できました。

{
  "data": {
    "deleteTodo": {
      "id": "5022aa80-278f-4b78-88e8-cb4f36717be9",
      "title": "My updated todo",
      "description": "This is my updated todo item",
      "owner": "Jane Doe"
    }
  }
}

おわりに

GraphQL API リゾルバーを JavaScript により記述する AWS AppSync Samples が提供されていたので試してみました。

今後新規作成する AppSync API は基本的にはリゾルバーの記述は VTL ではなく JavaScript で良いのでは無いでしょうか。また作成済みの AppSync API であってもリゾルバーの記述を VTL と JavaScript で混在もさせられるので、徐々に JavaScript に移行していくのも良いかもしれません。

参考

以上