まくろぐ

Node.js の Apollo モジュールで GitHub GraphQL API を利用する

更新:
作成:

Apollo Client のインストール

必要なパッケージ

Apollo パッケージは、GraphQL を使ったクライアントアプリやサーバーを作成するためのライブラリ群です。 クライアントアプリを作るためのライブラリは、@apollo/client というパッケージにまとめられています。 Web アプリのコンポーネントを作成するときは React がよく使われますが、Apollo は GraphQL を扱いやすくする React コンポーネント(QueryMutationSubscription)や React Hook 拡張(useQuery) などを提供しています。

Apollo Client のインストール
$ npm install --save @apollo/client graphql

Apollo クライアントは、Web ブラウザの fetch API を利用するため、Web アプリではない Node.js アプリから使用するには、fetch API の埋め合わせをするモジュールが必要です。 ここでは、cross-fetch パッケージをインストールしておきます。

fetch ライブラリのインストール
$ npm install --save cross-fetch

古いパッケージ

Apollo のクライアント系パッケージはいろいろな名前で提供されていましたが、すべて @apollo/client 以下にまとめられました。 次のようなパッケージはもう使用しません。

  • apollo-client: すべて @apollo/client に統合されたので使わない
  • apollo-boost: 次のように ApolloClient コンストラクタを使えばOK (import {ApolloClient} from '@apollo/client/core')
  • graphql-tag: GraphQL をパースするための gql@apollo/client に統合されている (import {gql} from '@apollo/client')

GitHub アクセストークンの発行

GitHub の GraphQL API を使用するには、下記のように POST リクエストのヘッダで GitHub アクセストークンを付加する必要があります。

authorization: Bearer a4304a13bc6cdd52509c90a38a676fce962ce518

アクセストークンを付加しないと、API 実行時に次のような HTTP 401 エラーが返されます。

ApolloError: Response not successful: Received status code 401

GitHub のアクセストークンは、下記の設定画面から Generate new token ボタンを押すことで作成できます。

GitHub / Settings / Developer settings / Personal Access Tokens

このとき、公開するデータのスコープ設定を行うのですが、repouser にチェックを入れておけば、大体必要な情報は取得できるようになります。

GitHub GraphQL API を使用する

次のサンプルコードでは、ApolloClient を使って GitHub GraphQL API を呼び出し、指定したリポジトリ (apollographql/apollo) の最新 Issue 5件分を取得しています。 このコードを実行できるようになれば、あとはクエリ部分を変更することでいろいろな情報を取得できます。

ポイントとしては、下記のあたりでしょうか。

  • cross-fetch/polyfill モジュールをインポートして、Web ブラウザの fetch 関数をエミュレートする
  • authorization ヘッダで GitHub のアクセストークンを指定する
  • GraphQL クエリを gql`クエリ文字列` という形で定義する

サンプルコード

main.ts
import {ApolloClient, ApolloError, InMemoryCache, gql} from '@apollo/client/core';
import 'cross-fetch/polyfill';  // グローバルな fetch 関数を定義する

// トークンは環境変数などから取得するのが常套手段
// const token = 'a4304a13bc6cdd52509c90a38a676fce962ce518';
const token = process.env.MYAPP_GITHUB_TOKEN;
if (typeof token === 'undefined') {
    throw new Error('MYAPP_GITHUB_TOKEN cannot be found');
}

// GraphQL クライアントを生成
const apolloClient = new ApolloClient({
  uri: 'https://api.github.com/graphql',
  headers: {authorization: `Bearer ${token}`},
  cache: new InMemoryCache(),
});

// 発行する GraphQL クエリ
const searchQuery = gql`
  query {
    search(query: "repo:apollographql/apollo is:issue", type: ISSUE, first: 5) {
      issueCount
      nodes {
        ... on Issue { number title }
      }
    }
  }
`;

// クエリを発行
apolloClient.query({query: searchQuery})
  .then(result => handleApolloResult(result.data))
  .catch(handleApolloError);

// GraphQL レスポンスをハンドル
function handleApolloResult(data: any) {
  const {issueCount, nodes} = data.search;
  console.log(`Num of issues: ${issueCount}`);
  for (const issue of nodes) {
    console.log(`* ${issue.number}: ${issue.title}`);
  }
}

// GraphQL のエラーをハンドル
function handleApolloError(err: ApolloError) {
  console.error(err.message);
}

実行結果

Num of issues: 176
* 937: Broken code display in blog for scaling GraphQL
* 934: Unknown directives
* 929: start apollo gateway
* 926: using REST services in apolo federation
* 909: Get a Graph Manager API key instructions need updating

関連記事

まくろぐ
サイトマップまくへのメッセージ