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"}}