graphql clientはApolloよりfetchでやった方がいいのではないかという件

# リポジトリ
https://github.com/gqlkit-repos/gqlkit-store
graphql client storeプラグインです。
これを、各フレームワークのcontextに突っ込んでやろうという魂胆
reduxはreact、vuexはvueという感じですが
クロスフレームワークでかつgraphqlの為の
client&storeというのを作ってみました。
nuxt.jsでは検証済

# resolverファーストアーキテクチャのgraphql client設計
```
.
├── index.js
└── resolvers
    ├── Mutation
    │   ├── createStaff.js
    │   └── deleteStaff.js
    ├── Query
    │   └── staffs.js
    ├── cache.js
    └── client.js
```
たったのこれだけ
と言いたいところですが
これを例えば、nuxtで使うなら、nuxtのpluginsディレクトリに突っ込むので
一見、まぁまぁな規模感あるように見えます。

というか、そもそもなのですが
クライアント側のvuexとかreduxだとかのストアが抱えている課題って
もうストアはストアで別個のフレームワークと捉えて設計した方が良いレベルではないかと思うので
これはなんか正解路線なのでは？と思っています。

ちなみにQueryとMutation以下のjsファイルはデモ用のファイルです。


# queryのコードの見た目も、mutationのコードの見た目もほぼ同じ
上のディレクトリツリーのstaffs.jsはこんな感じ

```javascript:staffs.js
import client from '../client'
import cache from '../cache'
import gql from 'graphql-tag'

export const demand = gql`
    query {
        staffs {
            id
            name
            age
            sex
        }
    }
`

export default async variables => {
    let re
    if (!cache.has('staffs').value()) {
        const { staffs } = await client.req(demand)
        cache.set('staffs', staffs).write()
        re = staffs
    } else {
        re = cache.get('staffs').value()
    }

    return re
}

```
mutationにあたるcreateStaff.jsはこんな感じ
mutationはrefetchしたいモジュールファイルをrefetchという名前で読み込みます。
そんでもってqueryでもmutationでも
クライアントツールは`client.req(demand, variables)`(variablesが必要ない場合は省略)

```javascript:createStaff.js
import client from '../client'
import cache from '../cache'
import gql from 'graphql-tag'
import refetch from "../Query/staffs";

export const demand = gql`
    mutation($name: String!, $age: Int!, $sex: String!) {
        createStaff(name: $name, age: $age, sex: $sex) {
            id
            name
            age
            sex
        }
    }
`

export default async variables => {
    const res = await client.req(demand, variables)
    const staff = res.createStaff
    const staffs = cache.get('staffs').value()
    staffs.push(staff)
    cache.set('staffs', staffs).write()
    
    return refetch()
}

```


# クライアントツールは21行のコードでqueryもmutationもOK!
fetchで書くとこんなシンプルになるとは正直、驚きました。
ただ、今後subscription導入のことも考えると
もうちょっと大きいファイルになる可能性はあります。
まだ、subscriptionは未経験なので。。。

```javascript:client.js
const GQLKIT_SERVER_END_POINT = process.env.GQLKIT_SERVER_END_POINT || 'http://localhost:4000/query'
const method = 'POST'
const headers = {
    'Content-Type': 'application/json',
    Accept: 'application/json'
}

export default {
    async req(demand, variables) {
        const res = await fetch(GQLKIT_SERVER_END_POINT, {
            method,
            headers,
            body: JSON.stringify({
                query: demand.loc.source.body,
                variables
            })
        })
        const { data } = await res.json()
        return data
    }
}


```

# キャッシュはどうするか？
キャッシュは完全切り分けの方針です。
Apolloのapiはキャッシュと密結合ですが
resolverファーストなgraphql clientアーキテクチャでは
キャッシュは完全別扱いにして
好きなin memory dbを使えば良いという方針で考えます。
resolverを書いて解決すれば良いじゃないか！という方針です。

僕は今のところlowdbを使っています。
ここはお好みで好きなもの使ってよしです。

```javascript:cache.js
import low from 'lowdb'
import Memory from 'lowdb/adapters/Memory'

const cache = low(new Memory())

cache.defaults({}).write()

export default cache

```

# まとめ
apolloがなぜ、あれほどまでに複雑なアーキテクチャを取っているのか
僕の知らない何らかの理由でああなっている可能性も大なので

これがベストアンサーだなんて到底言い切る事はできないです。
これはあくまで、1アイデアというものです。

あと、jsのオブジェクトをgormっぽい書き方で読み書き出来るような
ツールをご存知の方おられましたら教えて頂けると嬉しいです。

サーバーとクライアントで違うノウハウというのを最小限に抑えたい
ということで
graphqlサーバーのアーキテクチャを真似たプラグインを作ってみたという話でした。