Node.jsでGitHub GraphQL APIを実行する
GitHubの草をコマンドライン上で表示するnpmを作りました。
このnpmではGitHubの草情報を表示するために、日別のContribution数を取得しています。 今回初めてGraphQLを使ったので使い方をメモしておきます。
最初はAPIを使わず https://github.com/users/<username>/contributions
のsvgをfetchして配列形式で取得していたのですが、このページが正式のものか分からなかったこともあり、GraphQL APIでContributionが取得することにしました。
Contributionの取得はREST APIの方では見当たらなかったので現時点ではおそらくGraphQL APIでしかできないようです。
今回Node.jsでGitHub GraphQL APIを使うにあたって、GitHubが提供しているnpm @octokit/graphql
を使用しました。
サンプルコード
公式READMEに記載されているサンプルコードです。
GraphQLを実行するためのトークンと、欲しいデータを指定するクエリを設定する必要があります。
const graphqlWithAuth = graphql.defaults({ headers: { authorization: `token secret123`, }, }); const { repository } = await graphqlWithAuth(` { repository(owner: "octokit", name: "graphql.js") { issues(last: 3) { edges { node { title } } } } } `);
トークンの設定
トークンの取得
GitHubのGraphQLを実行するためにはGitHubの個人アクセストークンが必要です。
自分のケースの場合、権限のスコープは何も設定していなくても問題なく実行できましたが、用途に応じて設定します。
トークンの設定
トークンはGitHub上に公開してしまわないよう直書きにせず.env
ファイルに環境変数としてトークンを設定し、dotenvライブラリを使って取得します。
.env
GITHUB_TOKEN = <your_token>
jsファイル
const dotenv = require('dotenv') // .envファイルから環境変数を読み込む dotenv.config(); const graphqlWithAuth = graphql.defaults({ headers: { authorization: `token `token ${process.env.GITHUB_TOKEN}`` } })
npmとして公開する場合
npmとして公開する場合はユーザー自身のトークンを使います。
今回のnpmではグローバルインストールしてどのディレクトリでも実行したかったため、~/.fooenv
のように固有名の環境ファイルをホームディレクトリに作成しました。
環境設定ファイルを読み込むdotenv.config()
はデフォルトの場合コマンドを実行しているディレクトリ配下の.env
を参照するので、読み込む先を変更したい場合は引数に指定します。
const ENV_PATH = process.env.HOME + '/.grass_env' await fs.writeFile(ENV_PATH, `GITHUB_TOKEN = ${token}`) await dotenv.config({ path: ENV_PATH })
クエリの作成
GitHubにはExplorer - GitHub Docsというページがあり、 左側のExplorerから欲しい項目をチェックするだけで自動でクエリを作成してくれます。
今回は日毎のContributionが欲しいので、
user > contributionsCollection > contributionCalendar > weeks > contributionDays の
contributionCountとdateをチェックしました。
query getContribution { user(login: "yana-gi") { contributionsCollection { contributionCalendar { weeks { contributionDays { contributionCount date } } } } } }
▶︎ボタンを押すと以下のような結果が返ってきます。
{ "data": { "user": { "contributionsCollection": { "contributionCalendar": { "weeks": [ { "contributionDays": [ { "contributionCount": 0, "date": "2020-05-31T00:00:00.000+00:00" }, { "contributionCount": 0, "date": "2020-06-01T00:00:00.000+00:00" }, { "contributionCount": 0, "date": "2020-06-02T00:00:00.000+00:00" }, { "contributionCount": 0, "date": "2020-06-03T00:00:00.000+00:00" }, { "contributionCount": 0, "date": "2020-06-04T00:00:00.000+00:00" }, { "contributionCount": 0, "date": "2020-06-05T00:00:00.000+00:00" }, { "contributionCount": 0, "date": "2020-06-06T00:00:00.000+00:00" } ] }, { "contributionDays": [ { "contributionCount": 0, "date": "2020-06-07T00:00:00.000+00:00" }, -省略-
クエリには変数を指定することもできます。
query getContribution($userName:String!) { user(login: $userName) { contributionsCollection { contributionCalendar { weeks { contributionDays { contributionCount date } } } } } } // QUERY VARIABLES { "userName": "yana-gi" }
実際のコード
トークンとクエリを設定すれば、データを取得することができます。
実際に今回作ったnpmの該当コードを切り取ってみました。(一部改変)
const { graphql } = require('@octokit/graphql') const dotenv = require('dotenv') dotenv.config() const fetchContribution = async ({ userName }) => { const graphqlWithAuth = graphql.defaults({ headers: { authorization: `token `token ${process.env.GITHUB_TOKEN}`` } }) const query = `query getContribution($userName:String!) { user(login: $userName) { contributionsCollection { contributionCalendar { weeks { contributionDays { contributionCount date } } } } } }` return await graphqlWithAuth(query, { userName: userName }) } async function main (username) { const response = await fetchContribution({ userName: username }) const contributionWeeks = response.user.contributionsCollection.contributionCalendar.weeks console.log(contributionWeeks) } main(‘yana-gi’)