Node.js + Hapi + Couchbase  ~ Node.js + NoSQL(Couchbase) アプリ開発 ステップバイステップガイド (3) 

# はじめに

本シリーズの[前回の記事](https://qiita.com/yoshiyuki_kono/items/98c97531d5d1087a8069)では、WEBアプリケーション・フレームワークとして、Expressを用いました。
今回は、[Hapi](https://hapi.dev/)を使った例を紹介します。

## 利用バージョン
- Couchbase Server: 6.6
- Node.js: 15.4.0
- Node.js モジュール
 - couchbase: 3.1.1
 - hapi: 18.1.0
 - uuid: 8.3.2

# 実装

## Couchbase Server
以下、前提事項を記します。

### バケット
利用するバケット（`MyFirstBucket`）が存在している

### インデックス

検索で利用する項目に対して、インデックスが作成されている。

```sql
CREATE INDEX def_index_type ON MyFirstBucket(type)
```

### ユーザー

利用するバケットに対するアクセス権のあるユーザー（`Administrator`）を利用する。


## Node.js

### ライブラリインストール

```shell
npm install couchbase hapi uuid --save
```

### ソースコード

```javascript:app.js
const Hapi = require("hapi");
const Couchbase = require("couchbase");
const UUID = require("uuid");
 
const server = Hapi.Server({"host":"localhost","port":3000,routes:{cors: {origin: ['*']}}});

var cluster = new Couchbase.Cluster(
    'couchbase://localhost',
    {
      username: 'Administrator',
      password: 'password'
    }
  );

const bucket = cluster.bucket("MyFirstBucket");
const collection = bucket.defaultCollection();
const typeName = "user";
const statement = "SELECT `"+bucket._name+"`.* FROM `"+bucket._name+"` WHERE type = '"+typeName+"'";

const selectUsers = async (key) => { 
  const result = await cluster.query(statement);
  return result.rows;
}

const upsertUser = async (doc) => {
  try {
    const key = UUID.v4();
    const result = await collection.upsert(key, doc);
  } catch (error) {
    console.error(error);
  }
};
 
const init = async() => {
  await server.start(error=>{
      if(error){
        throw error;
      }
    });
  return server;
};

init().then(server => {
  console.log('Server running at:', server.info.uri);
}).catch(err => {
  console.log(err);
});

server.route({
    method:"GET",
    path:"/users",
    handler: async (request,h)=>{
      const rows = await selectUsers();
      return h.response(rows);
    }
});

server.route({
    method:"POST",
    path:"/user",
    handler: async (request, h)=>{
      try {
        request.payload["type"] = typeName;
        const result = await collection.upsert(UUID.v4(),request.payload);
        return h.response(request.payload);
      } catch (error) {
        console.error(error);
        return h.response("").code(500);
      }
    }
});
```
## 実行確認

### サーバー起動
```shell-session
$ node app.js
```

### アクセス結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/429fc985-748c-ab58-7e77-145a221decc8.png)

# 最後に

次のステップとして、Vue.jsを用いたフロントエンド・アプリケーションとの連携を予定しています(今回作成したPOSTのAPI `/user`については、そちらで利用例を紹介します)。


# 参考情報

Hapiは、バージョン17で、APIの大きな変更が行われています。新しいAPIについて、下記の記事を参考にしました（この記事では、データベースとしてMongoDBが使われています）。
[Developing RESTful APIs with Hapi](https://auth0.com/blog/developing-restful-apis-with-hapijs/)

Couchbase SDKも、メジャーアップデートにより、APIが大きく変更されています。
過去に発表された下記の二つの連続した記事では、古いバージョンが用いられていますが、基本構成の参考にしています。

[Create a RESTful API with Node.js, Hapi, and Couchbase NoSQL](https://blog.couchbase.com/create-restful-api-node-js-hapi-couchbase-nosql/)

[Going Full Stack with Node.js, Vue.js, and Couchbase NoSQL](https://blog.couchbase.com/full-stack-node-js-vue-js-couchbase-nosql/)