Azure Functions TypescriptでGraphQLを試してみる #Azure リレー
2020-03-18
azblob://2022/11/11/eyecatch/2020-03-18-azure-functions-graphql-000.png

こんにちは。本記事はAzure リレーの記事です。先週は清水さんのWindows の自動アップデート on Azure VM #Azure リレーです!

今回のテーマは Azure ということで、普段良く使っている Azure Functions について書いていこうと思います。Azure Function で GraphQL を使うことが出来るそうなので試してみました。

※本記事での Azure Functions の操作はすべて Azure Functions Core Tools です

関数の作成

まず、Azure Functions Core Tooksをインストールします。以下のコマンドを実行します

npm i -g azure-functions-core-tools

インストールができたらFunctionsのプロジェクトを作成します。

func init --typescript graphqlTest

今回言語は TypeScript で実装するので option で typescript を指定しています。プロジェクト名は "graphqlTest" です

さて実行したらプロジェクトが作成されますが、このプロジェクトにはまだ関数がないので関数を作成します

func new

上記のコマンドを実行すると

  • 作成する関数のトリガー
  • 作成する関数名

を尋ねられるのでトリガーは HTTP Trigger、関数名はそれっぽい名前にします。すると入力した関数名のフォルダが作成され以下のようなテンプレートのソースコードが作成されます。

import { AzureFunction, Context, HttpRequest } from "@azure/functions"

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    context.log('HTTP trigger function processed a request.');
    const name = (req.query.name || (req.body && req.body.name));

    if (name) {
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: "Hello " + (req.query.name || req.body.name)
        };
    }
    else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        };
    }
};

export default httpTrigger;

これで下準備は完了です

Azure FunctionsでApolloサーバーをセットアップする

Apollo サーバーとは 多くのGraphQLクライアントと互換性のある、オープンソースの仕様に準拠したGraphQLサーバーです 。今回はこちらを利用します。

まず、パッケージのインストールをします。Azure Functions用のパッケージをインストールします。

npm i apollo-server-azure-functions

インストールが完了したら先程の index.ts を以下のように書き換えます。

import { gql, ApolloServer } from "apollo-server-azure-functions";

const typeDefs = gql`
  type Query {
    hello: String
  }
`;

const resolvers = {
  Query: {
    hello: () => "Hello world"
  }
};

const server = new ApolloServer({ typeDefs, resolvers });

module.exports = server.createHandler();

そして index.ts と同じ階層にある function.json の出力バインディング名を "$ return " にします(重要)

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ],
  "scriptFile": "../dist/graphql/index.js"
}

これで準備完了です。Functionsを起動させてリクエストを送ってみましょう

npm start

"Hello world"と帰ってきていますね。GraphQLで叩けています。

ダミーデータを作成してデータの取得を行う

コード上にダミーデータを作成してそのデータにアクセスするようにしてみます。以下のようにコードを書き換えます

import { gql, ApolloServer } from "apollo-server-azure-functions";

type Person = {
  name: string;
  age: number;
};

const persons: Person[] = [
  {
    name: "Yusuke Tommimoto",
    age: 21
  },
  {
    name: "Yuta Kudo",
    age: 25
  }
];
const typeDefs = gql`
  type Query {
    hello: String
    User: [User]
  }

  type User {
    name: String
    age: Int
  }
`;

const resolvers = {
  Query: {
    hello: () => "Hello world",
    User: () => persons
  }
};

const server = new ApolloServer({ typeDefs, resolvers });

module.exports = server.createHandler();

これで persons というデータにHTTP経由でアクセスできるようになるはずです。試してみましょう。

名前だけ取得
名前と年齢を取得

ちゃんと取れました。

まとめ

Azure Funtions でもApollo サーバーが普通に使えました。Azure Functions の使い方の幅が広がっていきますね。

今回は Query しか試してませんが Mutation も動作します。Subscription はサポートしていないようです。