prisma-bindingのforwardToを使う
GraphQLサーバのresolver中の各クエリに、forwardTo
をそのまま代入する。
引数は、あとあとGraphQLServerの中のcontext
の中で、Prismaを指すendpoint名。
(下記の例ではprisma
)
import { GraphQLServer } from 'graphql-yoga'
import { Prisma, forwardTo } from 'prisma-binding'
const resolvers = <any> {
Query: {
user: forwardTo('prisma'),
users: forwardTo('prisma')
},
Mutation: {
createUser: forwardTo('prisma')
}
}
const server = new GraphQLServer({
typeDefs: 'src/generated/app.graphql',
resolvers,
context: req => ({
...req,
prisma: new Prisma({
typeDefs: 'src/generated/prisma.graphql',
endpoint: 'http://PRISMA_HOST',
}),
}),
})
server.start({ port: 4010,}, ({port}) => console.log(`GraphQL server is running on http://localhost:${port}`))
注:すいません、typescriptなのに<any>
で型指定を逃げています。
実行結果は以下の通り、ちゃんとusers
というクエリがそのままPrismaで参照できています。
もしクエリの引数や返り値を少し変形したい場合は、resolver内部を独自に実装しましょう。
付録:Prismaが提供するAPI、OpenCRUDとは
(実はここが一番大事かも)
OpenCRUDは、データ取得・更新に特化したGraphQL上のSDLです。
その意味を以下に記載します。
生のGraphQLの限界
GraphQLというのはAPIの形式です。クエリをjsonで送ってレスポンスもjsonで返す、という形式以外には、中身は何も規定していません。
そのため、功罪があります。
- いいところ: 自由にアプリでAPIの形式を決めてしまえるため、API開発者は楽です。
- 悪いところ: サービスやアプリごとにいろいろAPIが変わるので、API利用者は学習コストが高くなることです。
よくあるトレードオフです。
OpenCRUDの方針:GraphQL上に縛りを入れる
OpenCRUDではターゲットを「データ取得・更新用API」 とかなり絞り込み、APIに縛りを入れ、API利用者を少し楽にすることを目的にしています。
データ取得・更新で思い出すのは、デファクトとしてSQLというクエリ言語があることですが、OpenCRUDはGraphQL上でSQL文のプリミティブを実装したといってもいいと思います。雰囲気はSQLとMongoDBのクエリを混ぜたような雰囲気です。
比較してみます。
SQL | OpenCRUD on GraphQL | MongoDB |
---|---|---|
select * from users |
{ users {}} |
db.users.find({}) |
where a = 'value' |
where: { a: 'value' } |
{ a: "value" } |
where a in ('value1', 'value2') |
where { a_in: ['value1', 'value2'] } |
{ a: { $in: [ "value1", "value2" ] } } |
where a not in ('value1', 'value2') |
where { a_not_in: ['value1', 'value2'] } |
{ a: { $nin: [ "value1", "value2" ] } } |
where a = 'aval' AND b = 'bval' |
where: {OR: [ { a: "aval" }, { b: "bval" }]} |
{ $or: [ { a: "aval" }, { b: "bval" } ] } |
Web APIだとこれまではクエリの書き方の基準はRESTくらいで、RESTは縛りが強すぎて表現力が乏しかった。
GraphQLが自由度を増す仕掛けになったが自由度が高すぎるので、SQLレベルの書き方の基準を定義したOpenCRUDが出てきた。
SQLを使いこなす人からすると、いや別にSQLあるからいいんでない?と思うところなのですが、ここにある意味これまでとは違う世界観があります。
以下のような提案がPrismaのページでは書かれています。
- フロント寄りのAPI(自由度の低いクエリ)からバックエンド寄りのAPI(自由度の高いクエリ)まで全部GraphQLでよいではないか
- バックエンド寄りはOpenCRUDに標準化する
- APIの間の関係性はBindingで定義する
アプリ開発に必要なprisma-binding
ただ、まだ足りません。
JavaScriptのアプリを書く人にとってはクエリの結果を「意味のあるオブジェクト」にすることが大事で、そのためにORMが必要になってきて大体は自前で実装しなければいけない。
そこで、prisma-bindingは、GraphQLの型を使ってクエリの引数や返り値のオブジェクトの型定義を自動で作る。
役割分担は、クエリはOpenCRUD on GraphQL、その定義はprisma-bindingということになります。
RESTだと、クエリはRESTで定義はSwaggerという分担です。
最後は少し言葉が足りていないと思いますが、こういう世界観を作るのがprismaのすごいところだと思います。