@nuxt/axiosを使ってQiita Apiから記事一覧を取得する

GitHubpagesに自己紹介サイトを立てて少しずつ拡張しています。
今回、サイトにQiita記事へのリンクを貼りたい、けどリンクをペタペタ貼るのもつまらないということで、QiitaApiから私が書いた記事を取得しサイトに表示することにしました。

### 準備

```shell
yarn add @nuxtjs/axios
```

## QiitaのPATを使用する

Qiitaの設定でPATを生成、axiosのヘッダーに登録します。
ここではQiitaApiクラスを作成し、`asyncData(ctx:Context)`などで使用できるようにします。
（ここでは型定義の紹介は省きます）

```~/plugins/apiPlugins.ts
import { Plugin } from '@nuxt/types'
import QiitaApi from '~/api/QiitaApi'
import { QiitaApi as MockApi } from '~/mock/QiitaApi' // テストとかではモックに切り替えたい願望
import IApi from '~/types/Qiita/Api/v2/IApi'

// vueインスタンスから$qiitaApiを使用可能にする
declare module 'vue/types/vue' {
  interface Vue {
    $qiitaApi: IApi
  }
}

// this.$nuxt.contextから$qiitaApiを使用可能にする
declare module '@nuxt/types' {
  interface NuxtAppOptions {
    $qiitaApi: IApi
  }

  interface Context {
    $qiitaApi: IApi
  }
}

export const apiPlugin: Plugin = (context, inject): void => {
  const qiitaAxios = context.$axios.create({
    // baseURL: context.$config.baseURL
    baseURL: 'https://qiita.com/api/v2/',
    headers: { 
      // 環境変数に設定したQiita PATを登録
      Authorization: 'Bearer ' + process.env.PAT
    }
  })

  inject('qiitaApi', new QiitaApi(qiitaAxios))
}

export default apiPlugin
```

`GET /api/v2/authenticated_user/items`を使用することで、PATを設定したユーザーの記事を取得できます。

```~/api/QiitaApi.ts
import { NuxtAxiosInstance } from '@nuxtjs/axios'
import { PostData } from '~/types/Qiita/Api/v2/datas'
import IApi from '~/types/Qiita/Api/v2/IApi'

export default class QiitaApi implements IApi {
  private readonly axios: NuxtAxiosInstance

  constructor (axios: NuxtAxiosInstance) {
    this.axios = axios
  }

  public async getMyQiitaItems (): Promise<PostData[]> {
     const url = 'authenticated_user/items'
     try {
       const response : PostData[] = await this.axios.$get(url)
       return response
     } catch (e) {
       return Promise.reject(e)
     }
  }
}
```

APIから取得する記事のタイプ

```~/types/Qiita/Api/v2/datas.d.ts
/**
 * 投稿データ
 * https://qiita.com/api/v2/docs#%E6%8A%95%E7%A8%BF
 * */
export interface PostData{
  /** HTML形式の本文 */
  rendered_body:string
  /** Markdown形式の本文 */
  body:string
  /** この記事が共同更新状態かどうか (Qiita Teamでのみ有効) */
  coediting:boolean
  /** この記事へのコメントの数 */
  comments_count:number
  /** データが作成された日時 */
  created_at:string
  /** Qiita Teamのグループを表します。 */
  group:any
  /** 記事の一意なID */
  id:string
  /** この記事への「LGTM！」の数（Qiitaでのみ有効） */
  likes_count:number
  /** 限定共有状態かどうかを表すフラグ (Qiita Teamでは無効) */
  private:boolean
  /** 絵文字リアクションの数（Qiita Teamでのみ有効） */
  reactions_count:number
  /** 記事に付いたタグ一覧 */
  tags:any
  /** 記事のタイトル */
  title:string
  /** データが最後に更新された日時 */
  updated_at:string
  /** Qiita上のユーザー情報 */
  user: any
  /** 記事のurl */
  url:string
  /** Qiita上のユーザーを表します。 */
  page_views_count:number | undefined
  /** Qiita Teamのチームメンバー情報を表します */
  team_membership: any
}
```

## QiitaのPATを使用しない

publicリポジトリでGithub pages使うとenvファイルに書いたPATが丸見えになってしまうので他の方法を考えます。（もしかしたらGithubのsecretsなどをうまく使用する方法があるのかもしれませんが、現状思い浮かばなかったので...）

`GET /api/v2/items`で取得します。
まだ、大した記事数ではないので`page`や`per_page`パラメータは使用せず、検索クエリパラメータ`query`のみ使用します

```~/api/QiitaApi.ts
import { NuxtAxiosInstance } from '@nuxtjs/axios'
import { PostData } from '~/types/Qiita/Api/v2/datas'
import IApi from '~/types/Qiita/Api/v2/IApi'

export default class QiitaApi implements IApi {
  private readonly axios: NuxtAxiosInstance

  constructor (axios: NuxtAxiosInstance) {
    this.axios = axios
  }

  public async getMyQiitaItems (): Promise<PostData[]> {
    const url = 'items'
    try {
      const response: PostData[] = await this.axios.$get(url, {
        params: {
          query: 'user:sYamaz'//ユーザー名でフィルタリング
        }
      })
      return response
    } catch (e) {
      return Promise.reject(e)
    }
  }
}
```

## 終わりに

`@nuxt/axios`を使ってQiitaApiにアクセスし、自分の記事一覧を取得することができました。

ただし、使用制限（認証あり：1000回/時、認証なし：60回/時）があったり、記事自体そこまで頻繁に更新するものでもないことから、今回のような目的の場合はスクリプトなどでコードを自動生成するような方法の方が適していると思います。

Github Actionを使って定期的にApiアクセス＆コード自動生成→コミット/マージ→Github Pagesにデプロイとかできると面白そうです。

---
参考リンク

* [Qiita Api v2 ドキュメント](https://qiita.com/api/v2/docs)
* [axios.nuxtjs.org](https://axios.nuxtjs.org/extend#new-axios-instance)

自己紹介サイト

* [https://syamaz.github.io/website-nuxt/](https://syamaz.github.io/website-nuxt/)