世界最大級のクラウドサービスとして有名なAWS。とても多機能で色々なことができますが、使いこなすには難易度が高いサービスでもあります。
スマートフォンアプリ開発をされている方の中には、バックエンド(サーバ)側の知識にあまり馴染みが無いという方も多いのではないでしょうか。そういった方におすすめしたいのが、AWS Mobile Hubです。AWSの中でもモバイルアプリ開発に利用できる機能をまとめて提供しているサービスになります。
本連載では、AWS Mobile Hubの各種機能をMonacaアプリに組み込む方法を紹介します。

今回紹介するのはその中に含まれるサービスの一つである、データベース機能です。
AWS Mobile HubのデータベースにはAmazon DynamoDBが使われています。内部的には、DynamoDBの操作を行うのはAWS Lambda経由、さらにそのLambda呼び出しはAPI Gateway経由となっており、複雑な構成で実現されています。
しかし、AWS Mobile Hubはそういった複雑な部分を意識せずに利用できるようになっています。

前提条件

この記事では、まずAWSのアカウントは持っていることとします。また、MonacaアプリはMonaca CLIを使ってローカルコンピュータ上で開発します。Monaca CLIを利用するのでNode.jsもインストールされていることとします。

インストール

AWS Mobile HubのCLIツールをインストールします。

$ npm install -g awsmobile-cli

Monacaアプリの作成

Monaca CLIを使ってアプリを作ります。テンプレートはなんでも構いませんが、ここでは「Onsen UI > Onsen UI V2 JS Minimum」を選択します。

$ monaca create AWSHubDemo_DB

プロジェクトのルートディレクトリに移動し、srcディレクトリを作成しておいてください。

$ cd AWSHubDemo_DB
$ mkdir src

AWS Mobile Hubでプロジェクトを作る

AWS Mobile Hubのコンソールにサインインし、「Create Project」からウィザードに従ってプロジェクトを作成します。

プラットフォームは「Web」を選びます。
その際、「Enable web hosting with your app(ホスティングを有効にする)」のチェックは外しておきましょう。

ウィザードを進めるとコマンドが表示されますので、一番最後のコマンドをMonacaプロジェクトのルートディレクトリで実行します。

$ awsmobile init xxxxxxxxxxxx

実行すると、初期設定項目の入力を求められますが、すべてデフォルトのままEnterを押していきます。
すると、以下のようにキーの入力がが求められます。

Please enter the access key of the newly created user:
? accessKeyId:  (<YOUR_ACCESS_KEY_ID>)

Enterを押すとブラウザで AWS IAM のページが開くので、「プログラムによるアクセス」にチェックが入った状態で次に進みます。

AdministratorAccess 権限を割り当てて次へ進みます。

完了画面に表示される「アクセスキーID」と「シークレットアクセスキー」をコマンドラインから入力してください。

Please enter the access key of the newly created user:
? accessKeyId:  xxxxxxxxxxx
? secretAccessKey:  xxxxxxxxxxxxxxxxxxxxxxxxxxx

srcディレクトリ内に aws-exports.js というファイルができていれば完了です。

データベース設定

データベース設定はCLIで行います。まずはデータベースを有効化します。

$ awsmobile database enable --prompt

アクセス権限を設定します。今回はOpenとしています。

? Should the data of this table be open or restricted by user?
❯ Open
  Restricted

テーブル名を入力します。

? Table name: todos

次にカラムを設定します。カラム名は「team」、データタイプは「string」を指定します。

? What would you like to name this column: team
? Choose the data type: string

さらに他のカラムを追加するか聞かれるので、Yes と答えて todoId(数字)、text(string)の2つを追加します。

? Would you like to add another column: Yes
? What would you like to name this column: todoId
? Choose the data type: number
? Would you like to add another column: Yes
? What would you like to name this column: text
? Choose the data type: string
? Would you like to add another column: No

プライマリキーを聞かれますのでteamを選択します。このプライマリキーはユニークであると言うよりも、情報をフィルタリングするためのキーになります。team単位でタスクを管理するようなイメージです。

? Select primary key
❯ team
  todoId
  text

後はソートキーとしてtodoIdを指定、インデックスを追加するかどうかの質問にはNoと回答して完了です。

? Select sort key
❯ todoId
  text
  (No Sort Key)

? Add index (Y/n): n
Table todos saved.

CRUD APIの追加

次に作成したテーブルに対してCRUD操作を行うAPIを追加します。

$ awsmobile cloud-api enable --prompt

APIをどう作成するか選びます。これは「Create CRUD API for an existing Amazon DynamoDB table(既存のDynamoDBのテーブル)」を選んでください。

? Select from one of the choices below. (Use arrow keys)
  Create a new API
❯ Create CRUD API for an existing Amazon DynamoDB table

そうするとDynamoDBのテーブルが一覧に並びますので、そこから先程作成した「todos」を選びます。

? Select Amazon DynamoDB table to connect to a CRUD API
❯ todos

完了したら、最後にpushします。

$ awsmobile push

これでLambdaに関数が作られ、それを操作するAPI Gatewayのエンドポイントが作られます。以下は awsmobile push を実行した際に表示されるログです。

$ awsmobile push

checking the backend contents
   building cloud-api
      zipping todos
   done
   generating backend project content
   done
backend build artifacts are saved at: 
/path/to/monaca-project/awsmobilejs/.awsmobile/backend-build

preparing for backend project update: MonacaDB
   uploading todos-20180815100255.zip
   upload Successful  todos-20180815100255.zip
done

updating backend project: MonacaDB
awsmobile api call successful
waiting for the cloud formation to complete
cloud-api update finished with status code: CREATE_COMPLETE

Successfully updated the backend awsmobile project: MonacaDB

retrieving the latest backend awsmobile project information
awsmobile project's details logged at:
    awsmobilejs/#current-backend-info/backend-details.json
awsmobile project's specifications logged at:
    awsmobilejs/#current-backend-info/mobile-hub-project.yml
awsmobile project's access information logged at: 
    awsmobilejs/#current-backend-info/aws-exports.js
awsmobile project's access information copied to: 
    src/aws-exports.js
contents in #current-backend-info/ is synchronized with the latest in the aws cloud

JavaScriptの実装と変換

gulpを使ってソースの変換を行いますので、npm install コマンドで以下のライブラリをインストールしてください。

  • gulp
  • browserify
  • babelify
  • babel-register
  • babel-preset-es2015
  • vinyl-source-stream

src/index.js を作成し、AWSのJavaScriptライブラリ aws-amplify から利用したい機能を取り出します。データベース機能を利用するには「API」モジュールが必要です。

src/index.js

import Amplify, { API } from 'aws-amplify';
import awsmobile from './aws-exports.js';
Amplify.configure(awsmobile);
window.API = API;

このファイルのままではMonacaから使えないので、ソースを変換します。今回はgulpを使います。プロジェクトのルートディレクトリ以下に gulpfile.babel.js を作成します。

gulpfile.babel.js

import gulp from 'gulp';
import browserify from "browserify";
import babelify from "babelify";
import source from "vinyl-source-stream";

gulp.task("default", () => {
  browserify({
      entries: ["./src/index.js"]
    })
    .transform(babelify, {presets: ['es2015']})
    .bundle()
    .pipe(source("app.js"))
    .pipe(gulp.dest("www/js"));
});

gulp.task('watch', function(){
  gulp.watch('./src/*.js', ['default']);
});

さらに .babelrc を作成します。これでES2015の構文が使えます。

.babelrc

{
  "presets": ["es2015"]
}

最後に package.json に以下のコマンドを追加します。

"scripts": {
  "watch": "node node_modules/gulp/bin/gulp.js watch"
},

これで準備完了です。 npm run watch を実行すると、 src/index.js の内容をコンパイルして www/js/app.js として書き出します。
こうして書き出されたファイルを、www/index.html 内に読み込みます。

<script src="js/app.js"></script>

JavaScriptの実装

全体のコードはこちらにアップロードされています。
database.html にデータベース接続処理が実装されています。

データの一覧を取得

データの取得は API.get() で実行します。第一引数には「テーブル名 + CRUD」という名前を指定します。結果としてテーブルのデータが配列形式で返ってきます。

const updateTodo = async () => {
  const todos = await API.get('todosCRUD', `/todos/${team}`)
  Todo = todos;
  const html = [];
  for (todo of Todo) {
    html.push(`<ons-list-item>${todo.text} <div onclick="deleteTodo('${todo.todoId}')"> (削除)</div></ons-list-item>`);
  }
  me.querySelector('.todos').innerHTML = html.join("");
}

データの登録

データの登録は API.post() を使います。bodyパラメータに登録内容を指定します。
この時のレスポンスは登録が成功したというメッセージのみになります。そのため、登録したデータを表示するためには再度データ一覧を取得する必要があります。

const postTodo = async (text) => {
  return await API.post('todosCRUD', '/todos', {
    body: {
      todoId: Todo.length + 1,
      text: text,
      team: team
    }
  })
};

データの更新も同じフォーマットで、メソッドが API.put() に変わるだけです。

データの削除

データの削除は API.del() メソッドになります。また、第二引数に指定するURLが若干変わって、 /object/ というパスが入ります。

const deleteTodo = async (todoId) => {
  await API.del('todosCRUD', `/todos/object/${team}/${todoId}`)
  updateTodo();
}

AWSのクラウドデータベースは様々なサービスが組み合わさって提供されていますが、AWS Mobile Hubからであれば裏側の複雑さを気にすることなく使えます。NoSQL型なのでAPIを叩くだけで容易にCRUD処理を行えるのが魅力といえるでしょう。

今回のコードはgoofmint/Monaca_AWSHub_Databaseにアップロードしてあります。実装時の参考にしてください。

Access Your Database - AWS Mobile

API Guide