KibelaのAPIで遊んでみた

# はじめに

Qiitaに似たようなサービスで、[Kibela](https://kibe.la/)という情報共有サービスがあります。
※外部サイト誘導ではありません。

弊社では、

- Qiitaは社外向けの技術ブログ
- Kibelaは社内向けの情報共有

という位置付けだと思うのですが、
どちらのサイトもWeb APIが提供されています。

Kibelaでは、リソースのやりとりに`GraphQL`が採用されているのですが、
今回は、KibelaのAPIを使用してGraphQLで遊んでみたいと思います。

# GraphQLとは

- [GraphQL](https://graphql.org/)
- [kibela-api](https://github.com/kibela/kibela-api-v1-document)

Web APIの為の規格の一つ。
他に認知度の高い規格としては、`REST`などが存在します。
GraphAPIは、以下の要素で構成されています。

- APIの仕様を表現するスキーマ言語
    - GraphQL SDL (SDL)
- データの取得・更新などを行うクエリ言語
    - GraphQL query language (DSL)

リソースのやり取りにはGraphQL query languageが記述されたdocumentを送信し、
データの取得や更新を行います。

GET・POSTで送信方法が異なります。
GETの場合は、query, operationName等のクエリをそれぞれHTTPのQuery Stringに指定して送信します。
POSTの場合は、query, operationName等が含まれたjsonをRequest Bodyに指定して送信します。

# 実行環境

- macOS: 10.15.7
- Postman: 7.33.1

# 共通パラメーター

※kibela-apiは認証が必要な為、基本的にPOST Methodでのリクエストです。

```text:RequestHeader
Content-Type: application/json
Accept: application/json
Authorization:　Bearer $KIBELA_ACCESS_TOKEN
```

# とりあえず叩いてみる

```graphql:Query
query getCurrentUser {
    currentUser {
        account
        realName
        locale
    }
}
```

```json:ResponseBody
{
    "data": {
        "currentUser": {
            "account": "aucfan-murakami",
            "realName": "登録時の実名が入ります。",
            "locale": "ja"
        }
    }
}
```

# リソースを取得してみる

日報用のSchemaから、最新の記事を100件取得してみます。

```graphql:Query
query getDailyReport($dailyReportID: ID!) {
    group(id: $dailyReportID) {
        notes(first: 100, orderBy: {field: PUBLISHED_AT, direction: DESC}) {
            edges {
                node {
                    contentHtml
                }
            }
        }
    }
}
```

```json:Variables
{
    "dailyReportID": "IDが入ります。"
}
```

```json:ResponseBody
{
    "data": {
        "group": {
            "notes": {
                "edges": [
                    {
                        "node": {
                            "contentHtml": "ここに記事の内容が入っています。"
                        }
                    },
                    {
                        "node": {
                            "contentHtml": "ここに記事の内容が入っています。"
                        }
                    }
                ]
            }
        }
    }
}
```

# リソースを作成してみる

日報用のSchemaへ、記事を一件作成してみます。

```graphql:Query
mutation createDailyReport($dailyReportID: ID!) {
    createNote(input: {title: "Test", content: "Test", coediting: false, groupIds: [$dailyReportID]}) {
        clientMutationId
    }
}
```

```json:Variables
{
    "dailyReportID": "IDが入ります。"
}
```

```json:ResponseBody
{
    "data": {
        "createNote": {
            "clientMutationId": null
        }
    }
}
```

# リソースを更新してみる

先程作成した記事を更新してみます。

```graphql:Query
mutation updateDailyReport($dailyReportID: ID!, $noteID: ID!) {
    updateNote(input: {
        id: $noteID,
        baseNote: {
            title: "Test",
            content: "Test",
            coediting: false,
            groupIds: [$dailyReportID]
        },
        newNote: {
            title: "Test12345",
            content: "Test12345",
            coediting: true,
            groupIds: [$dailyReportID]
        },
        draft: false
    }) {
        clientMutationId
    }
}
```

```json:Variables
{
    "dailyReportID": "日報グループのIDが入ります。",
    "noteID": "記事のIDが入ります。"
}
```

```json:ResponseBody
{
    "data": {
        "updateNote": {
            "clientMutationId": null
        }
    }
}
```

この操作を実行する場合、
現在のリソースの情報を何らかの形で取得しておく必要がありますね。(記事のタイトルや内容等)

# リソースを削除してみる

先程作成した記事を削除してみます。

```graphql:Query
mutation updateDailyReport($noteID: ID!) {
    deleteNote(input: {id: $noteID}) {
        clientMutationId
    }
}
```

```json:Variables
{
    "noteID": "記事のIDが入ります。"
}
```

```json:ResponseBody
{
    "data": {
        "deleteNote": null
    },
    "errors": [
        {
            "message": "The user has no permission to perform the specified action",
            "locations": [
                {
                    "line": 2,
                    "column": 5
                }
            ],
            "path": [
                "deleteNote"
            ],
            "extensions": {
                "code": "NO_PERMISSION",
                "id": "記事のIDが入ります"
            }
        }
    ]
}
```

削除型の操作は、管理ユーザーのみが実行出来るようです。

# やってみた系

社内用に、定期実行型の日報提出&フォーマットチェッカーを
PHP Composer Packageとして作成しました。

# 参考になった記事など

- [「GraphQL」徹底入門 ─ RESTとの比較、API・フロント双方の実装から学ぶ](https://employment.en-japan.com/engineerhub/entry/2018/12/26/103000)
- [GraphQLを導入してみて得た知見と雑感。GraphQLはタイタニックの救命ボードになりえるかも](https://qiita.com/jabba/items/0bf3d2436215394391a7)
- [Kibela Web API を使ってみました 〜 GraphQL 予備知識ゼロ昭和おじさんのゴールデンウィーク奮闘記 〜](https://inokara.hateblo.jp/entry/2019/05/06/095616)

# 最後に

GraphQLで遊びたかっただけです...笑
次はAPI側を作ってみたいです！