できるだけ最小構成のAWS AppSync

## 作りたいもの
CDKでつくるMutation, Query, Subscriptionをするだけのできるだけ小さいサンプル

完成品 https://github.com/tky/app-sync-example

## 注意点

Subscripiton使うためにはschemaをcodeで定義する必要があります。
ネットによくある```appsync.Schema.fromAsset```を使ってschemaを定美すると、
[Unable to add subscription. Schema definition mode must be ...](
https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/aws-appsync/lib/schema.ts#L167
)とかいっておこられてしまいます。


aws-cdk/aws-appsync-alpha使っているので将来breaking changesがある可能性があります。

## 実装

importないsampleで苦しむことが多いので一応。。

```
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { Table, AttributeType } from "aws-cdk-lib/aws-dynamodb";
import {
  AuthorizationType,
  Directive,
  GraphqlApi,
  Field,
  GraphqlType,
  InputType,
  MappingTemplate,
  ObjectType,
  PrimaryKey,
  Values,
  ResolvableField,
  Schema,
} from "@aws-cdk/aws-appsync-alpha";
import { RemovalPolicy } from "aws-cdk-lib";
```


nameとageだけ持つuserを定義してみます。
MutationするためにInputTypeも。

```
const typeUser = new ObjectType("User", {
      definition: {
        id: GraphqlType.string({ isRequired: true }),
        name: GraphqlType.string({ isRequired: true }),
        age: GraphqlType.int({ isRequired: false }),
      },
    });

    const typeUserInput = new InputType("UserInput", {
      definition: {
        name: GraphqlType.string({ isRequired: true }),
        age: GraphqlType.int({ isRequired: false }),
      },
    });

    const schema = new Schema();
    schema.addType(typeUser);
    schema.addType(typeUserInput);
```


```
const api = new GraphqlApi(this, "api", {
      name: "app-sync-example-api",
      schema,
      authorizationConfig: {
        defaultAuthorization: {
          authorizationType: AuthorizationType.API_KEY,
        },
      },
      xrayEnabled: false,
    });

    const table = new Table(this, "table", {
      tableName: "app-sync-example-table",
      partitionKey: {
        name: "id",
        type: AttributeType.STRING,
      },
      removalPolicy: RemovalPolicy.DESTROY,
    });
```


DataSourceはDynamoDB

```
    const dataSource = api.addDynamoDbDataSource("data_source", table);
```

Query


```
schema.addQuery(
      "getUser",
      new ResolvableField({
        returnType: typeUser.attribute(),
        args: {
          id: GraphqlType.id({ isRequired: true }),
        },
        dataSource,
        requestMappingTemplate: MappingTemplate.dynamoDbGetItem("id", "id"),
        responseMappingTemplate: MappingTemplate.dynamoDbResultItem(),
      })
    );
```

Mutation
idはautoではなく指定するようにしています。

```
    schema.addMutation(
      "addUser",
      new ResolvableField({
        returnType: typeUser.attribute(),
        args: {
          id: GraphqlType.string({ isRequired: true }),
          input: typeUserInput.attribute({ isRequired: true }),
        },
        dataSource,
        requestMappingTemplate: MappingTemplate.dynamoDbPutItem(
          PrimaryKey.partition("id").is("id"),
          Values.projecting("input")
        ),
        responseMappingTemplate: MappingTemplate.dynamoDbResultItem(),
      })
    );
```

idは指定するからってInputTypeにいれるとだめでした。

```
 // 動かないサンプル
 const typeUserInput = new InputType("UserInput", {
      definition: {
        // idをInputのdefinitionにいれるとだめ
        id: GraphqlType.string({ isRequired: true }),
        name: GraphqlType.string({ isRequired: true }),
        age: GraphqlType.int({ isRequired: false }),
      },
    });

 schema.addMutation(
      "addUser",
       ...
        requestMappingTemplate: MappingTemplate.dynamoDbPutItem(
          Values.projecting("input")
        )
      })
    );
```


Subscription

```
    schema.addSubscription(
      "updatedUser",
      new Field({
        returnType: typeUser.attribute(),
        args: { id: GraphqlType.id({ isRequired: true }) },
        directives: [Directive.subscribe("addUser")],
      })
    );
```

awsのconsoleログインしてAWS AppSyncから作ったAPIを選択、Queriesで試せます。
[コマンドでするための方法](https://github.com/tky/app-sync-example/tree/main/scripts)も用意したのでお好みでどうぞ