/graffito

Graphql Interface for Pathom3

Primary LanguageClojureEclipse Public License 1.0EPL-1.0

Graffito

An alternative way to build Graphql interfarces powered by Pathom 3 and Lacinia.

Graffito takes a Lacinia Schema with a few extra attributes that allow Lacinia to resolve Graphql queries using Pathom 3 resolvers. This means you write Pathom3 resolvers/mutations and with minimal configuration you can also offer a Graphql graphql

Usage

To expose a Pathom 3 graph as Graphql first you need to have Pathom3 graph. Nothing in particular has to be done when you write the pathom 3 mutations and resolvers. Once the pathom 3 graph is available you write a lacinia schema that describes the objects and queries that we are going to expose in the graphql app.

By convention Graffito matches Graphql types & attributes to namespaced attributes resolved by pathom. If the convention doesn't match the existing attributes, you can specifiy the name of a give type attribute.

Attributes

The default convetion is to convert any attribute of a graphql type to: type.attribte-name. Example: the Graphql attribute min_players from the type BoardGame is by default resolved by a pathom as :board-game.min-players. In this case, no configuration was necessary inside the lacinia schema.

To match an attribute to a different pathom attribute you use :pathom/attribute to specify the name of the attribute to match the Grapqhl attr. Example:

:GameRating
{:description "A member's rating of a particular game."
:fields
{:game   {:type        (non-null :BoardGame)
          :description "The Game rated by the member."}
 :rating {:type             (non-null Int)
          :description      "The rating as 1 to 5 stars."
          :pathom/attribute :rating/value}}}   ;; Here we are saying that we want to match GameRating.rating to the pathom attr :rating/value

Resolvers

If not specified each query in GraphQl will be resolved by the default Lacinia resolver. This resolver basically calls pathom and converts the attributes to the values expected by the Lacinia resolver. As in any other Lacinia app, a custom resolver can be specified using :resolve :your/resolver.

Mutations

For mutations you need to specify the corresponding Pathom3 mutation. Example:

:mutations
 {:rate_game
  {:type        :BoardGame
   :description "Establishes a rating of a board game, by a Member.
   On success (the game and member both exist), selects the BoardGame.
   Otherwise, selects nil and an error."
   :args
   {:game_id   {:type             (non-null ID)
                :pathom/attribute :board-game/id}
    :member_id {:type             (non-null ID)
                :pathom/attribute :member/id}
    :rating    {:type        (non-null Int)
                :description "Game rating as a number between 1 and 5."}}
   :resolve     [:pathom/mutation graffito.board-game-geek.resolver/rate!]}} ;; Specify the corresponding pathom mutation

Subscriptions

Graphql Subscriptions are not yet supported :(

Putting it all together

(ns  graffito.board-game-geek.core
 (:require [com.walmartlabs.lacinia :as lacinia)
           [graffito.core :as graffito]


(def pathom-index ....)

(def schema
  (graffito/compile (graffito/load-schema! "cgg-schema.edn")
                    pathom-index))

(lacinia/execute schema "{ game_by_id (id: \"1236\") { id name }}" nil pathom-index) 

For more complete examples check This test

Why

Pathom 3 liberates you from the Type hell that Graphql forces you into, so why do we wnat to use Graphql? Reach. Graphql lets you reach to the Javascript community. A lot of tools have been developed around graphql and convincing a javascript developr to use EQL is as hard as convincing a Clojurescript developer to use Strings to write queries. Graffito opens your graph to both audiences.

Warning

We have been using Graffito internally in a medium size Pathom 3 app. The graphql queries we have tested in top of Graffito are relatively simple. We haven't yet tested more advanced features like Fragment, aliases, variables. ETC.

Previus Work

Graffito has been heavily inspired by the ides from Graffiti and this discussion.

License

Copyright © 2021 Juan.maya

EPLv1.0 is just the default for projects generated by clj-new: you are not required to open source this project, nor are you required to use EPLv1.0! Feel free to remove or change the LICENSE file and remove or update this section of the README.md file!

Distributed under the Eclipse Public License version 1.0.