0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Postgraphile+Apolloをテストで立ち上げる

Posted at

Postgraphileはnode.jsで動く。
Postgresから簡単にGraphQL作れるらしい
こことかを見て試す。
環境はWindowsServer2012

Postgraphileインストール

Postgresは既にローカルで動いているので省略。

npm install postgraphile

実際には今回は面倒なので-gでインストール。(npxでローカルでも実行できるはず?)
4.12.8がインストールされた。

起動は以下のコマンド
postgraphile -c postgres://postgres:password@localhost:5432/postgres --watch --enhance-graphiql --dynamic-json

これで起動出来た

  ‣ GraphQL API:         http://localhost:5000/graphql
  ‣ GraphiQL GUI/IDE:    http://localhost:5000/graphiql
  ‣ Postgres connection: postgres://postgres:[SECRET]@localhost/postgres (watching)

このURLにアクセスして確認、しようと思ったがpublic schemaだった。--schema testでスキーマを指定できる。
実際に昔作ったtestテーブルでクエリ発行

query MyQuery {
  allTests(first: 10) {
    edges {
      node {
        id
      }
    }
  }
}
{
  "data": {
    "allTests": {
      "edges": [
        {
          "node": {
            "id": 1
          }
        },
        {
          "node": {
            "id": 2
          }
        },
        {
          "node": {
            "id": 3
          }
        }
      ]
    }
  }
}

と簡単に出来た。

HTTPサーバから立上げ

node.jsのサーバ経由で使う方法もある。
公式にも載っている。

const express = require("express");
const { postgraphile } = require("postgraphile");

const app = express();

app.use(
  postgraphile(
    process.env.DATABASE_URL || "postgres://user:pass@host:5432/dbname",
    "public",
    {
      watchPg: true,
      graphiql: true,
      enhanceGraphiql: true,
    }
  )
);

app.listen(process.env.PORT || 5000);

ただ、これで実行すると
Ensure that there is only one instance of "graphql" in the node_modules directory.
のエラーが出てしまったので、何かインストールしたものが悪いのかもしれない。

"resolutions": {
 "graphql": "15.5.0"
}

のように書いて解決、とネット上では書いてあるが、色々面倒そうなのでここでは諦める。。。
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0",@apolloの中には書いてあった。

なお、Productionでの推奨オプションは

const postgraphileOptions = {
  subscriptions: true,
  retryOnInitFail: true,
  dynamicJson: true,
  setofFunctionsContainNulls: false,
  ignoreRBAC: false,
  extendedErrors: ["errcode"],
  appendPlugins: [require("@graphile-contrib/pg-simplify-inflector")],
  graphiql: false,
  enableQueryBatching: true,
  disableQueryLog: true, // our default logging has performance issues, but do make sure you have a logging system in place!
  legacyRelations: "omit",
  pgSettings(req) {
    /* TODO */
  },
};

と書いてあるが詳しくは見ていない。

その他サーバ側

セキュリティ関係については公式にいくつか書いてある。
DoSに関してはhttps://www.apollographql.com/blog/graphql/security/securing-your-graphql-api-from-malicious-queries/を参照。
一般的にはhttps://github.com/graphile/persisted-operationsのプラグインを入れるのが良いらしい。

オプションにbodySizeLimitがある。
graphqlDepthLimitやgraphqlCostLimitのような制限を使いたい場合はPro版が存在する、っぽい。

うまく動かないときは
こことか参考?

GraphQLよりRestAPIだろ、という場合はRestAPIを作るPostgRESTの記事

Apolloクライアント

GraphQLに繋ぐ側として、今回はついでにApolloのクライアント側だけ試しておく。
こここことかここを見ながら。

apolloクライアント

Reactではなくnode.js単体で返すパターンでテスト。
あまり情報がないがここが多少参考になる。

まずは必要なものをインストール
npm install @apollo/client graphql apollo-boost node-fetch react

サーバはpostgraphileコマンドで立ち上げている。
expressを使って/apiにアクセスするとGraphQLから取得するようにnode.js側を組んでみた。
試行錯誤でごちゃごちゃやっているので、不要な処理もあるはず。

import apolloClient, { gql } from "apollo-boost";
import express from "express";
import apolloInMemoryCache from 'apollo-cache-inmemory';
import apolloHttpLink from 'apollo-link-http';
import nodeFetch from 'node-fetch';
global.fetch = nodeFetch;
const { HttpLink } = apolloHttpLink;
const { InMemoryCache } = apolloInMemoryCache;
const { ApolloClient } = apolloClient;
const app = express();
var server = app.listen(3000, function(){
    console.log("Node.js is listening to PORT:" + server.address().port);
});

const client = new ApolloClient({
  uri: 'http://localhost:5000/graphql', // このパターンだとこれは必要ないはず
  cache : new InMemoryCache(),
  link:  new HttpLink( {uri:'http://localhost:5000/graphql'})
});

async function getTestProps() {
    const {data} = await client.query({
      query: gql`
      query MyQuery { allTests(first: 10) { edges { node { id name } } } }
      `,
    });
    return data
}

// 外部から取得する際の処理
app.get("/api", async function(req, res, next){
    let data =  await getTestProps();
    res.json(data);
});

これでデータが返ってきた。

{"allTests":{"edges":[{"node":{"id":1,"name":"one","__typename":"Test"},"__typename":"TestsEdge"}
,{"node":{"id":2,"name":"two","__typename":"Test"},"__typename":"TestsEdge"}
,{"node":{"id":3,"name":"therr","__typename":"Test"},"__typename":"TestsEdge"}],"__typename":"TestsConnection"}}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?