1
2

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 5 years have passed since last update.

GraphQLの旅(8) Prismaにそのままリクエストを転送する(付録 OpenCRUDとは)

Posted at

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で参照できています。

image.png

もしクエリの引数や返り値を少し変形したい場合は、resolver内部を独自に実装しましょう。

prisma-bindingを使った独自クエリの実装の仕方

付録: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のすごいところだと思います。

1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?