Amplify Data をセットアップする
このガイドでは、Amplify Data をセットアップする方法を学びます。これには、TypeScript を使用してデータモデルを定義してリアルタイム API とデータベースを構築し、認可ルールで API をセキュアにすることが含まれます。また、カスタムユースケースにスケーリングするために AWS Lambda を使用することも紹介します。
開始する前に、以下が必要です:
Amplify Data を使うと、数分でデータベースによるセキュアで リアルタイム API を構築できます。TypeScript を使用してデータモデルを定義した後、Amplify はリアルタイム API をデプロイします。この API は AWS AppSync によって提供され、Amazon DynamoDB データベースに接続されています。認可ルールで API をセキュアにでき、AWS Lambda でカスタムユースケースにスケーリングできます。
データバックエンドを構築する
すでに npm create amplify@latest を実行している場合、amplify/data/resource.ts ファイルが表示されます。これは、データバックエンドを構成するための中心的な場所です。最も重要な要素は schema オブジェクトで、バックエンドのデータモデル (a.model()) とカスタムクエリ (a.query())、ミューテーション (a.mutation())、サブスクリプション (a.subscription()) を定義します。
import { a, defineData, type ClientSchema } from '@aws-amplify/backend';
const schema = a.schema({ Todo: a.model({ content: a.string(), isDone: a.boolean() }) .authorization(allow => [allow.publicApiKey()])});
// Used for code completion / highlighting when making requests from frontendexport type Schema = ClientSchema<typeof schema>;
// defines the data resource to be deployedexport const data = defineData({ schema, authorizationModes: { defaultAuthorizationMode: 'apiKey', apiKeyAuthorizationMode: { expiresInDays: 30 } }});すべての a.model() は、クラウドで以下のリソースを自動的に作成します:
- レコードを保存するための DynamoDB データベーステーブル
- レコードを作成、読取 (リスト/取得)、更新、削除するためのクエリおよびミューテーション API
- 各レコードが最初に作成されたとき、または最後に更新されたときを追跡するのに役立つ
createdAtおよびupdatedAtフィールド - レコードの作成、更新、削除イベントをサブスクライブするためのリアルタイム API
allow.publicApiKey() ルールは、API キーで認証されたすべての人が、todo を作成、読取、更新、削除できることを指定します。
これらのリソースをクラウドサンドボックスにデプロイするには、ターミナルで次の CLI コマンドを実行します:
npx ampx sandbox --outputs-format dart --outputs-out-dir libアプリケーションコードをデータバックエンドに接続する
クラウドサンドボックスが起動して実行されている場合、API エンドポイント URL や API キーなどのデータバックエンドへの接続情報を含む amplify_outputs.json ファイルも作成されます。
フロントエンドコードをバックエンドに接続するには、以下を実行する必要があります:
- Amplify ライブラリを Amplify クライアント構成ファイル (
amplify_outputs.json) で構成する - Amplify ライブラリから新しい API クライアントを生成する
- エンドツーエンドの型安全性を備えた API リクエストを実行する
プロジェクトルートディレクトリから pubspec.yaml を見つけて変更し、Amplify プラグインをプロジェクト依存関係に追加します。
dependencies: amplify_api: ^2.0.0 amplify_flutter: ^2.0.0 flutter: sdk: flutter次のコマンドを実行して依存関係をインストールします。開発環境によっては、この手順を IDE 経由で実行したり、自動的に実行される場合もあります。
flutter pub get次に、Flutter アプリケーション用の GraphQL クライアントコードを生成します。Amplify Data は GraphQL を使用して、クエリ、ミューテーション、サブスクリプションリクエストを実行します。生成された GraphQL クライアントコードは、GraphQL リクエストを手動で作成して Dart コードにマップする必要なく、完全に型付きされた API リクエストを作成するのに役立ちます。
npx ampx generate graphql-client-code --format modelgen --model-target dart --out <path_to_flutter_project>/lib/models最後に、lib/main.dart ファイルの main() 関数をカスタマイズして、必要なプラグインを Flutter アプリケーションに追加します:
import 'package:amplify_api/amplify_api.dart';import 'package:amplify_flutter/amplify_flutter.dart';import 'package:flutter/material.dart';
import 'amplify_outputs.dart';import 'models/ModelProvider.dart';
Future<void> main() async { try { final api = AmplifyAPI( options: APIPluginOptions( modelProvider: ModelProvider.instance ) ); await Amplify.addPlugins([api]); await Amplify.configure(amplifyConfig);
safePrint('Successfully configured Amplify'); } on Exception catch (e) { safePrint('Error configuring Amplify: $e'); }
runApp(const MyApp());}バックエンドにデータを書き込む
ページに新しい todo を作成するフローティングアクションボタンを追加しましょう。
// ... main()class MyApp extends StatelessWidget { const MyApp({super.key});
Widget build(BuildContext context) { return const MaterialApp( home: MyHomePage(), ); }}
class MyHomePage extends StatefulWidget { const MyHomePage({super.key});
State<MyHomePage> createState() => _MyHomePageState();}
class _MyHomePageState extends State<MyHomePage> {
Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'Your todos', ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () async { final newTodo = Todo(content: "New Flutter todo", isDone: false); final request = ModelMutations.create(newTodo); final response = await Amplify.API.mutate(request: request).response; if (response.hasErrors) { safePrint('Creating Todo failed.'); } else { safePrint('Creating Todo successful.'); } }, tooltip: 'Add todo', child: const Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); }}アプリケーションを実行してフローティングアクションボタンをクリックすると、todo が作成されたことを示すログが表示されるはずです:
Creating Todo successful.バックエンドからデータを読み込む
次に、すべての todo をリストし、todo が追加された後に todo を再度取得します:
最初に、todos を追跡する新しいリストと、最初にレンダリングされる時に todo リストをフェッチする機能を追加します:
// ...main()
class MyApp extends StatelessWidget { const MyApp({super.key});
Widget build(BuildContext context) { return const MaterialApp( home: MyHomePage(), ); }}
class MyHomePage extends StatefulWidget { const MyHomePage({super.key});
State<MyHomePage> createState() => _MyHomePageState();}
class _MyHomePageState extends State<MyHomePage> { List<Todo> _todos = [];
void initState() { super.initState(); _refreshTodos(); }
Future<void> _refreshTodos() async { try { final request = ModelQueries.list(Todo.classType); final response = await Amplify.API.query(request: request).response;
final todos = response.data?.items; if (response.hasErrors) { safePrint('errors: ${response.errors}'); return; } setState(() { safePrint(todos); _todos = todos!.whereType<Todo>().toList(); }); } on ApiException catch (e) { safePrint('Query failed: $e'); } }
Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'Your todos', ), _todos.isEmpty == true ? const Center( child: Text( "The list is empty.\nAdd some items by clicking the floating action button.", textAlign: TextAlign.center, ), ) : ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, itemCount: _todos.length, itemBuilder: (context, index) { final todo = _todos[index]; return CheckboxListTile.adaptive( value: todo.isDone, title: Text(todo.content!), onChanged: (isChecked) async {}, ); }), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () async { final newTodo = Todo(content: "New Flutter todo", isDone: false); final request = ModelMutations.create(newTodo); final response = await Amplify.API.mutate(request: request).response; if (response.hasErrors) { safePrint('Creating Todo failed.'); } else { safePrint('Creating Todo successful.'); } }, tooltip: 'Add todo', child: const Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); }}リアルタイム更新をサブスクライブする
リアルタイム更新を追加するには、Amplify Data のサブスクリプション機能を使用できます。これにより、アプリケーションの onCreate, onUpdate, および onDelete イベントをサブスクライブできます。この例では、新しい todo が追加されるたびにリストを追加します。
ページがレンダリングされるとき、onCreate イベントをサブスクライブしてから、Widget が破棄されるときにアンサブスクライブします。
// ...main()// ...MyApp// ...MyHomePage
class _MyHomePageState extends State<MyHomePage> { List<Todo> _todos = []; StreamSubscription<GraphQLResponse<Todo>>? subscription;
void initState() { super.initState(); _refreshTodos(); _subscribe(); }
void dispose() { _unsubscribe(); super.dispose(); }
void _subscribe() { final subscriptionRequest = ModelSubscriptions.onCreate(Todo.classType); final Stream<GraphQLResponse<Todo>> operation = Amplify.API.subscribe( subscriptionRequest, onEstablished: () => safePrint('Subscription established'), ); subscription = operation.listen( (event) { safePrint('Subscription event data received: ${event.data}'); setState(() { _todos.add(event.data!); }); }, onError: (Object e) => safePrint('Error in subscription stream: $e'), ); }
void _unsubscribe() { subscription?.cancel(); subscription = null; }
// ..._refreshTodos() // ...build()}結論
成功しました! Amplify Data で初めてのリアルタイム API とデータベースを作成する方法を学びました。
次のステップ
Amplify Data で発見することがたくさんあります。詳細については、以下をご覧ください: