

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

# `APPSYNC_JS` ランタイムのバンドル、TypeScript、ソースマップ
<a name="additional-utilities"></a>

TypeScript は、型の安全性と早期エラー検出を提供することで AWS AppSync 開発を強化します。TypeScript コードをローカルで記述し、`APPSYNC_JS` ランタイムで使用する前に JavaScript にトランスパイルできます。このプロセスは、TypeScript のインストールと `APPSYNC_JS` 環境の tsconfig.json の設定から始まります。その後、esbuild などのバンドルツールを使用して、コードをコンパイルしてバンドルできます。Amplify CLI は GraphQL スキーマからタイプを生成し、リゾルバーコードでこれらのタイプを使用できます。

リゾルバーと関数コードでは、`APPSYNC_JS` 要件を満たす限り、カスタムライブラリと外部ライブラリの両方を活用できます。バンドルツールは、コードを 1 つのファイルに結合して使用します AWS AppSync。ソースマップを含めると、デバッグに役立ちます。

## ライブラリの活用とコードのバンドル
<a name="using-external-libraries"></a>

リゾルバーと関数コードでは、`APPSYNC_JS` 要件を満たす限り、カスタムライブラリと外部ライブラリの両方を活用できます。これにより、アプリケーション内の既存のコードを再利用できます。複数のファイルで定義されたライブラリを使用するには、[esbuild](https://esbuild.github.io/) などのバンドルツールを使用してコードを 1 つのファイルに結合し、リ AWS AppSync ゾルバーまたは関数に保存する必要があります。

コードをバンドルするときは、次の点に留意してください。
+ `APPSYNC_JS` は、ECMAScript モジュール (ESM) のみをサポートします。
+ `@aws-appsync/*` モジュールは `APPSYNC_JS` に統合されており、バンドルすべきではありません。
+ `APPSYNC_JS` ランタイム環境は、コードがブラウザ環境では実行されないという点で NodeJS に似ています。
+ オプションでソースマップを含めることができます。ただし、ソースコンテンツを含めないでください。

  ソースマップの詳細については、「[ソースマップの使用](#source-maps)」を参照してください。

例えば、`src/appsync/getPost.resolver.js` にあるリゾルバーコードをバンドルするには、次の esbuild CLI コマンドを使用することができます。

```
$ esbuild --bundle \
--sourcemap=inline \
--sources-content=false \
--target=esnext \
--platform=node \
--format=esm \
--external:@aws-appsync/utils \
--outdir=out/appsync \
 src/appsync/getPost.resolver.js
```

## コードのビルドと TypeScript での作業
<a name="working-with-typescript"></a>

[TypeScript](https://www.typescriptlang.org/) は Microsoft が開発したプログラミング言語で、TypeScript タイピングシステムとともに JavaScript のすべての機能を備えています。TypeScript を使用すると、タイプセーフなコードを記述し、ビルド時にコードを AWS AppSyncに保存する前にエラーやバグを検出できます。`@aws-appsync/utils` パッケージは完全に型指定されています。

`APPSYNC_JS` ランタイムは TypeScript を直接サポートしていません。コードを AWS AppSyncに保存する前に、まず TypeScript コードを `APPSYNC_JS` ランタイムがサポートする JavaScript コードにトランスパイルする必要があります。TypeScript を使用してローカル統合開発環境 (IDE) にコードを記述できますが、 AWS AppSync コンソールで TypeScript コードを作成することはできません。

開始する前に、プロジェクトに [TypeScript](https://www.typescriptlang.org/download) がインストールされていることを確認してください。次に、[TSConfig](https://www.typescriptlang.org/tsconfig) を使用して `APPSYNC_JS` ランタイムと連携するように TypeScript のトランスコンパイル設定を構成します。使用できる基本 `tsconfig.json` ファイルの例を次に示します。

```
// tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
   "noEmit": true,
   "moduleResolution": "node",
  }
}
```

その後、esbuild などのバンドルツールを使用して、コードをコンパイルしてバンドルできます。たとえば、 にある AWS AppSync コードを持つプロジェクトの場合`src/appsync`、次のコマンドを使用してコードをコンパイルしてバンドルできます。

```
$ esbuild --bundle \
--sourcemap=inline \
--sources-content=false \
--target=esnext \
--platform=node \
--format=esm \
--external:@aws-appsync/utils \
--outdir=out/appsync \
 src/appsync/**/*.ts
```

### Amplify Codegen を使用する
<a name="working-with-amplify-codegen"></a>

[Amplify CLI](https://docs.amplify.aws/cli/) を使用してスキーマのタイプを生成できます。`schema.graphql` ファイルが置かれているディレクトリから以下のコマンドを実行し、プロンプトを確認して codegen を設定します。

```
$  npx @aws-amplify/cli codegen add
```

特定の状況 (スキーマの更新時など) で codegen を再生成するには、以下のコマンドを実行します。

```
$ npx @aws-amplify/cli codegen
```

その後、生成された型をリゾルバーコードで使用できます。例として、次のスキーマがあるとします。

```
type Todo {
  id: ID!
  title: String!
  description: String
}

type Mutation {
  createTodo(title: String!, description: String): Todo
}

type Query {
  listTodos: Todo
}
```

生成された型は、次の例の AWS AppSync 関数で使用できます。

```
import { Context, util } from '@aws-appsync/utils'
import * as ddb from '@aws-appsync/utils/dynamodb'
import { CreateTodoMutationVariables, Todo } from './API' // codegen

export function request(ctx: Context<CreateTodoMutationVariables>) {
	ctx.args.description = ctx.args.description ?? 'created on ' + util.time.nowISO8601()
	return ddb.put<Todo>({ key: { id: util.autoId() }, item: ctx.args })
}

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

### TypeScript でのジェネリックの使用
<a name="working-with-typescript-generics"></a>

ジェネリックスは用意されているいくつかの型で使用できます。例えば、以下のスニペットは `Todo` タイプです。

```
export type Todo = {
  __typename: "Todo",
  id: string,
  title: string,
  description?: string | null,
};
```

`Todo` を利用するサブスクリプション用のリゾルバーを書くことができます。お使いの IDE では、型定義とオートコンプリートのヒントを参考にして、`toSubscriptionFilter` 変換ユーティリティを適切に使用してください。

```
import { util, Context, extensions } from '@aws-appsync/utils'
import { Todo } from './API'

export function request(ctx: Context) {
  return {}
}

export function response(ctx: Context) {
  const filter = util.transform.toSubscriptionFilter<Todo>({
    title: { beginsWith: 'hello' },
    description: { contains: 'created' },
  })
  extensions.setSubscriptionFilter(filter)
  return null
}
```

## バンドルのリンティング
<a name="using-lint-with-bundles"></a>

`esbuild-plugin-eslint` プラグインをインポートすることで、バンドルを自動的にリントできます。その後、eslint 機能を有効にする `plugins` 値を指定することで有効化できます。以下は、esbuild JavaScript API を `build.mjs` というファイルで使用しているスニペットです。

```
/* eslint-disable */
import { build } from 'esbuild'
import eslint from 'esbuild-plugin-eslint'
import glob from 'glob'
const files = await glob('src/**/*.ts')

await build({
  format: 'esm',
  target: 'esnext',
  platform: 'node',
  external: ['@aws-appsync/utils'],
  outdir: 'dist/',
  entryPoints: files,
  bundle: true,
  plugins: [eslint({ useEslintrc: true })],
})
```

## ソースマップの使用
<a name="source-maps"></a>

JavaScript コードでインラインソースマップ (`sourcemap`) を提供できます。ソースマップは、JavaScript または TypeScript コードをバンドルしていて、入力ソースファイルへの参照をログやランタイム JavaScript エラーメッセージに表示したい場合に便利です。

`sourcemap` はコードの最後に表示する必要があります。以下の形式の 1 行のコメントで定義されます。

```
//# sourceMappingURL=data:application/json;base64,<base64 encoded string>
```

例を示します。

```
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibGliLmpzIiwgImNvZGUuanMiXSwKICAibWFwcGluZ3MiOiAiO0FBQU8sU0FBUyxRQUFRO0FBQ3RCLFNBQU87QUFDVDs7O0FDRE8sU0FBUyxRQUFRLEtBQUs7QUFDM0IsU0FBTyxNQUFNO0FBQ2Y7IiwKICAibmFtZXMiOiBbXQp9Cg==
```

ソースマップは esbuild で作成できます。以下の例は、コードをビルドしてバンドルするときに esbuild JavaScript API を使用してインラインソースマップを組み込む方法を示しています。

```
/* eslint-disable */
import { build } from 'esbuild'
import eslint from 'esbuild-plugin-eslint'
import glob from 'glob'
const files = await glob('src/**/*.ts')

await build({
  sourcemap: 'inline',
  sourcesContent: false,
  
  format: 'esm',
  target: 'esnext',
  platform: 'node',
  external: ['@aws-appsync/utils'],
  outdir: 'dist/',
  entryPoints: files,
  bundle: true,
  plugins: [eslint({ useEslintrc: true })],
})
```

特に、`sourcemap` および `sourcesContent` オプションでは、各ビルドの最後にソースマップをインラインで追加し、ソースコンテンツは含めないように指定しています。慣例として、ソースコンテンツは `sourcemap` には含めないことをお勧めします。これを無効にするには、`sources-content` を `false` に設定します。

ソースマップの仕組みを説明するために、リゾルバーコードがヘルパーライブラリのヘルパー関数を参照する次の例を確認してください。このコードには、リゾルバーコードとヘルパーライブラリーのログステートメントが含まれています。

**./src/default.resolver.ts** (自身のリゾルバー)

```
import { Context } from '@aws-appsync/utils'
import { hello, logit } from './helper'

export function request(ctx: Context) {
  console.log('start >')
  logit('hello world', 42, true)
  console.log('< end')
  return 'test'
}

export function response(ctx: Context): boolean {
  hello()
  return ctx.prev.result
}
```

**.src/helper.ts** (ヘルパーファイル)

```
export const logit = (...rest: any[]) => {
  // a special logger
  console.log('[logger]', ...rest.map((r) => `<${r}>`))
}

export const hello = () => {
  // This just returns a simple sentence, but it could do more.
  console.log('i just say hello..')
}
```

リゾルバーファイルをビルドしてバンドルすると、リゾルバーコードにはインラインソースマップが含まれます。リゾルバーを実行すると、CloudWatch ログに次のエントリが表示されます。

![\[CloudWatch log entries showing resolver code execution with inline source map information.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/cloudwatch-sourcemap.jpeg)


CloudWatch ログのエントリを見ると、2 つのファイルの機能がバンドルされ、同時に実行されていることがわかります。各ファイルの元のファイル名もログにはっきりと反映されています。