GraphQL
This page explains how Pathom consumes GraphQL services via dynamic resolvers
Pathom consumers GraphQL by first adapting a GraphQL schema to the Pathom format. The follow sections will explain how each part of GraphQL translates to Pathom.
How Pathom translates from GraphQL
It's important to remember that Pathom and GraphQL use different base abstraction ideas.
While GraphQL is based typed schema, Pathom works with attributes as the primary building blocks.
Let's take a look in an example to see what this translation look like, take the following GraphQL schema as an example:
type Query {
me: User
}
type User {
id: ID
name: String
}
When we connect to Pathom, it's required that you define a namespace to prefix all the names that we will import from the GraphQL service.
For this example I'll pick the name "gqldemo"
, this is what the import code looks
like:
(p.gql/connect-graphql
{::p.gql/namespace "gqldemo"}
request-graphql-fn)
The request function
The request-graphql-fn
must be a function that takes a GraphQL string as input and
output the GraphQL JSON results converted to Clojure data structures. It's important
that you use strings for the keys (not keywords).
With that configuration, we should expect the following attributes to be available from Pathom:
:gqldemo.Query/me
:gqldemo.User/id
:gqldemo.User/name
An example query to fetch the name of the current user:
[{:gqldemo.Query/me
[:gqldemo.User/name]}]
Scalars
Pathom doesn't do anything about scalars, in the context of Pathom integration with GraphQL they are irrelevant.
Object Types
For each object type in GraphQL, Pathom will add one attribute to hold the type itself and one attribute for each property of that type in GraphQL.
Getting back to our previous example, for the type User
we will have this:
; type name
:gqldemo.types/User
; attributes for properties
:gqldemo.User/id
:gqldemo.User/name
It's important to note that :gqldemo.types/User
is marked as a transient attribute.
This means you can't query for it, but it's part of the query resolution.
Having these types named allow us to reference the type (which means we can access all attributes of it) in a simple way.
Query Type
Query types are first defined in the same way as the object types. The special thing about the Query type is that Pathom will make it accessible from anywhere, so you can enter the GraphQL from its properties.
Interfaces
From Pathom point of view, interfaces work backwards. Pathom will find all the implementations of the interface and link them will all implementor object types.
Mutations
All mutations are imported all namespaced by the user prefix plus .Mutation
, for
example:
type Mutation {
setMessage(message: String): String
}
Here is how we call it:
[(gqldemo.Mutation/setMessage {:message "Some message"})]
The namespace at the mutation params are not relevant, with or without a namespace Pathom will send them as-is.
Depending on the mutation you may need to add a sub-query to satisfy the GraphQL syntax.
Taking another example from GraphQL documentation:
input MessageInput {
content: String
author: String
}
type Message {
id: ID!
content: String
author: String
}
type Query {
getMessage(id: ID!): Message
}
type Mutation {
createMessage(input: MessageInput): Message
updateMessage(id: ID!, input: MessageInput): Message
}
Using the same prefix as before, this is how we can call createMessage:
[{(gqldemo.Mutation/createMessage {:id 123 :content "Some message" :author "Margaret"})
[:gqldemo.Message/id
:gqldemo.Message/content]}]
Complete tutorial
If you like to see a more complete integration example check the GraphQL Tutorial.