Any Amplify Graphical APIを使用して反応型スクリプトフロントエンドを使用する方法



導入
AWS Amplify モバイルおよびWebアプリケーションの開発プラットフォームです.それは、ビルトインAmazon Web Services(AWS)であり、異なったAWSサービス、例えば、ラムダ関数、認知的ユーザプールとappsync graphql APIのような足場です.これは手動でモバイルWebアプリケーション用のAWSインフラストラクチャを設定し、開発速度が速くなります.増幅も自分自身を持っているdocumentation siteopen source
この記事では、HTMLスクリプトAPIを設定する方法を示します.

AWSアカウント
AmplifyはAWSサービスであるため、AWS Console . アカウントを持っていない場合は、1つを作成します.注:クレジットカードが必要です.しかし、パンデミックのために.AWS Educate あなたがクレジットカードなしでアカウントのサインアップすることができるように導入されました.しかし、このチュートリアルでは、クラウドに公開されたときに何もコストはかかりません.

セットアップ反応プロジェクト
反応フロントエンドのために我々は単純な作成反応アプリ(CRA)を使用します.
これらのCLIコマンドを実行し、それを作成し、
npx create-react-app amplify-typescript-demo --template typescript
cd amplify-typescript-demo
npm install --save aws-amplify

セットアップアンプ
確認してくださいAmplify CLI グローバルにインストールされ、設定されます.
公式ドキュメントは非常によく説明し、ビデオも持っています.Install and configure Amplify CLI
CLIが正しく構成された後、プロジェクトで増幅を初期化できます.
amplify init
このコマンドwilは、プロジェクト内で増幅を初期化し、いくつかの情報が必要です.我々は基本的なCRAのアプリを持っているので、我々は単にEnterキーを押して、デフォルトのオプションで続行できます.
 Enter a name for the project `amplifytypescriptdem`
 Enter a name for the environment `dev`
 Choose your default editor: `Visual Studio Code`
 Choose the type of app that you\'re building `javascript`
 What javascript framework are you using `react`
 Source Directory Path: `src`
 Distribution Directory Path: `build`
 Build Command: `npm run-script build`
 Start Command: `npm run-script start`
 Do you want to use an AWS profile? `Yes`
 Please choose the profile you want to use `amplify-workshop-use`

グラフAPI APIを追加する
今、GraphSQL APIを実行することによって追加できます.
amplify add api
これはいくつかの質問をすることによって驚くでしょう
 Please select from one of the below mentioned services: `GraphQL`
 Provide API name: `DemoAPI`
 Choose the default authorization type for the API: `API key`
 Enter a description for the API key: My Demo API
 After how many days from now the API key should expire (1-365): `7`
 Do you want to configure advanced settings for the GraphQL API: `No, I am done.`
 Do you have an annotated GraphQL schema? `No`
 Do you want a guided schema creation? `Yes`
 What best describes your project: `Single object with fields (e.g., “Todo” with ID, name, description)`
 Do you want to edit the schema now? `No`
これはgraphql APIを生成します.オープンamplify/backend/api/DemoAPI/schema.graphql モデルを表示するには
これには基本的なTODOモデルが含まれます.
type Todo @model {
  id: ID!
  name: String!
  description: String
}

模擬とAPIのテスト
APIはテストされる準備ができています!任意のラムダ関数やappsyncを手動で設定する必要はありません.すべては、増幅によって管理されます.
APIをテストするには、クラウドに配備する必要さえありません.AmplifyはローカルAPIを局所的に模擬する機能を持っています.
amplify mock api
再び、これはまたいくつかの質問をします.そして、ここではtypescriptの部分が来る.このコールは自動的に我々の反応アプリのTypeScriptモデルを生成します.単に選択typescript デフォルトのオプションを指定します.
 Choose the code generation language target `typescript`
 Enter the file name pattern of graphql queries, mutations and subscriptions `src/graphql/**/*.ts`
 Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions `Yes`
 Enter maximum statement depth [increase from default if your schema is deeply nested] `2`
 Enter the file name for the generated code `src/API.ts`
 Do you want to generate code for your newly created GraphQL API `Yes`
最後に、APIが実行されているローカルアドレスでメッセージを取得する必要があります.
AppSync Mock endpoint is running at http://192.168.0.143:20002
ブラウザでそのアドレスを開き、GraphSQLを参照してください.

リストの作成と一覧表示
デモデータを作成してテストするためのいくつかの突然変異とクエリがあります.
mutation CreateTodo {
  createTodo(
    input: { name: "Blog Post", description: "Write a Blog Post about Amplify" }
  ) {
    description
    name
  }
}

mutation CreateTodo2 {
  createTodo(
    input: { name: "Dinner", description: "Buy groceries and cook dinner" }
  ) {
    description
    name
  }
}

query ListTodos {
  listTodos {
    items {
      name
      description
    }
  }
}

反応アプリでAPIを使用してください
最初のステップを増幅して設定をインポートすることです.The config オブジェクトは./aws-exports . このファイルはAmplifyによって生成され、手動で編集されるべきではありません.
import Amplify from 'aws-amplify';
import config from './aws-exports';
Amplify.configure(config);

ラップ増幅API.グラフ
AmplifyはGraphSQL APIを消費する機能を提供します.したがって、アポロクライアントのような別のGraphSQLクライアントを使用する必要はありません.
ちょっともう少し安全なタイプの小さなラッパーを作成してください.
import { API, graphqlOperation } from "aws-amplify";
import { GraphQLResult, GRAPHQL_AUTH_MODE } from "@aws-amplify/api";

export interface GraphQLOptions {
  input?: object;
  variables?: object;
  authMode?: GRAPHQL_AUTH_MODE;
}

async function callGraphQL<T>(query: any, options?: GraphQLOptions): Promise<GraphQLResult<T>> {
  return (await API.graphql(graphqlOperation(query, options))) as GraphQLResult<T>
}

export default callGraphQL;
機能callGraphQL<T> が一般的であり、API.graphql(...) . 結果は型からですGraphQLResult<T> . この小さなラッパーなしで、我々は常にそれをキャストしなければなりませんGraphQLResult<T> .

クエリ一覧
新しいフォルダを作るsrc/models ファイルの中todo.ts . これは、TODO用のフロントエンドモデルと、オブジェクトをマップする関数を含むファイルです.
import { ListTodosQuery } from "../API";
import { GraphQLResult } from "@aws-amplify/api";

interface Todo {
  id?: string;
  name?: string;
  description?: string;
}

function mapListTodosQuery(listTodosQuery: GraphQLResult<ListTodosQuery>): Todo[] {
  return listTodosQuery.data?.listTodos?.items?.map(todo => ({
    id: todo?.id,
    name: todo?.name,
    description: todo?.description
  } as Todo)) || []
}

export default Todo;
export { mapListTodosQuery as mapListTodos }
ここで何が起こっているのですか.まず、インポートListTodosQuery …からAPIとGraphQLResult . API.ts を返します.GraphQLResult GraphSQL APIが返す汎用インターフェイスです.
次は簡単ですTodo インタフェースと関数mapListTodosQuery . これはオブジェクトを型からマップするGraphQLResult<ListTodosQuery> 我々の配列にToDo .

ラッパーを使う
内部App.tsx 最後に、GraphSQL APIをラッパーで呼び出すことができます.
import React, { useState, useEffect } from "react";
import { listTodos } from "./graphql/queries";
import { ListTodosQuery } from "./API";
import Todo, { mapListTodos } from "./models/todo";

// omitted Amplify.configure

function App() {
  const [todos, setTodos] = useState<Todo[]>();

  useEffect(() => {
    async function getData() {
      try {
        const todoData = await callGraphQL<ListTodosQuery>(listTodos);
        const todos = mapListTodos(todoData);
        setTodos(todos);
      } catch (error) {
        console.error("Error fetching todos", error);
      }
    }
    getData();
  }, []);

  return (
    <div className="App">
      {todos?.map((t) => (
        <div key={t.id}>
          <h2>{t.name}</h2>
          <p>{t.description}</p>
        </div>
      ))}
    </div>
  );
}
私たちは、useState<Todo[]> フック.
Then useEffect はAPIを最初に呼び出すために使われます.API呼び出しは非同期であるため、async function getData() が定義されている.この関数は、以前に作成したラッパーを使用しますcallGraphQL() としてジェネリック型を定義するListTodosQuery これは自動生成されたAPIからインポートされます.T .引数としてlistTodos が渡される.これは、また、Amplifyによって自動生成される実際のGraphSQL質問です.結果はmapListTodos todosを配列として返す関数です.その後、状態を更新する.

todo変異の作成
突然変異を送るには、ラッパーを再利用できます.
const name = 'Learn Amplify'
const description = 'Start first Amplify project'

const response = await callGraphQL<CreateTodoMutation>(createTodo, {
        input: { name, description },
      } as CreateTodoMutationVariables);
これらの型をインポートする必要があります.CreateTodoMutation : 突然変異が戻るものの型createTodo : グラフの突然変異CreateTodoMutationVariables : 渡される引数の型.これはinput 新しいtodoのプロパティを含むオブジェクトです.

購読
サブスクリプションはリアルタイムアップデートを有効にします.新しいtodoが作成されるたびに、サブスクリプションは新しいToDoを発します.我々はこの新しいtodoでtodoリストを更新することができます.
そのために、ジェネリックインターフェースを作成しますSubscriptionValue :
interface SubscriptionValue<T> {
  value: { data: T };
}
また、TODOモデルの新しいマッピング機能も必要です.
function mapOnCreateTodoSubscription(createTodoSubscription: OnCreateTodoSubscription): Todo {
  const { id, name, description } = createTodoSubscription.onCreateTodo || {};
  return {
    id, name, description
  } as Todo
}
インApp.tsx 別の追加useEffect 購読を扱う
import Todo, { mapOnCreateTodoSubscription } from './models/todo';
import { SubscriptionValue } from './models/graphql-api';
import { onCreateTodo } from './graphql/subscriptions';

useEffect(() => {
  // @ts-ignore
  const subscription = API.graphql(graphqlOperation(onCreateTodo)).subscribe({
    next: (response: SubscriptionValue<OnCreateTodoSubscription>) => {
      const todo = mapOnCreateTodoSubscription(response.value.data);
      console.log(todo);
      setTodos([...todos, todo]);
    },
  });

  return () => subscription.unsubscribe();
});
これはおそらく、PHPスクリプトを使用している最も困難な部分です.
The Api.graphql(...) 関数の戻り値はPromise<GraphQLResult> | Observable<object>のみObservablesubscribe 関数.Without the @ts-ignore タイプスクリプトコンパイラはsubscribe 型には存在しませんPromise<GraphQLResult> | Observable<object> .
残念ながら、我々は単にas Observable 増幅SDKがエクスポートしないのでObservable 種類既にAGitHub issues そのために.
サブスクライブ関数自体は、next プロパティは、新しいtodoが作成されるたびに呼び出される関数を必要とします(コールバックとして考えることができます).
その関数のパラメータはSubscriptionValue<OnCreateTodoSubscription . パスresponse.value.datamapOnCreateTodoSubscription を返します.その後、状態は新しいtodoで更新されます.最後に、戻り値のステートメントでは、サブスクリプションが解除され、メモリリークを避けるためにコンポーネントがアンマウントされます.
これは少し冗長です.これは、callGraphQL 機能
function subscribeGraphQL<T>(subscription: any, callback: (value: T) => void) {
  //@ts-ignore
  return API.graphql(graphqlOperation(subscription)).subscribe({
    next: (response: SubscriptionValue<T>) => {
      callback(response.value.data);
    },
  });
}
これは再びサブスクリプションを返す汎用関数です.を受け入れるsubscription とコールバック.The callback が次のハンドラで呼び出され、response.value.data が引数として渡されます.
The useEffect 購読をこれにリファクションすることができます.
const onCreateTodoHandler = (
  createTodoSubscription: OnCreateTodoSubscription
) => {
  const todo = mapOnCreateTodoSubscription(createTodoSubscription);
  setTodos([...todos, todo]);
};

useEffect(() => {
  const subscription =
    subscribeGraphQL <
    OnCreateTodoSubscription >
    (onCreateTodo, onCreateTodoHandler);

  return () => subscription.unsubscribe();
}, [todos]);
The onCreateTodoHandler は、マッピング関数を呼び出し、新しいToDoで状態を更新する責任があります.
インuseEffect 我々は、新しいsubscribeGraphQL ラッパー関数onCreateTodo サブスクリプションとonCreateTodoHandler . 前と同様に、コンポーネントがアンマウントされると、サブスクリプションが取り消されます.

概要
Amplifyは非常に迅速にGrapql APIを足場にすることもできますし、自動でもフロントエンド用のtypescriptコードを生成します.いくつかのラッパー機能では、ボイラープレートコードを減らすことができますし、安全性を受け入れるタイプ.
完全なソースコードはGitHub
コメントを残してください.