Skip to content
/ grafeo Public

A GraphQL document and schema language based on S-expressions in Clojure & ClojureScript

License

Notifications You must be signed in to change notification settings

r0man/grafeo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Grafeo

https://img.shields.io/clojars/v/grafeo.svg https://travis-ci.org/r0man/grafeo.svg https://versions.deps.co/r0man/grafeo/status.svg https://versions.deps.co/r0man/grafeo/downloads.svg

Grafeo is Clojure and ClojureScript library that provides a S-expression based language for GraphQL documents and schemas.

Usage

Require the library.

(require '[clojure.pprint :refer [pprint]])
(require '[grafeo.core :as gql])

Define a GraphQL document in s-expression format. Take a look at the doc folder to learn how to write GraphQL documents and schemas in S-expression format.

(def my-document
  '((human
     [(id "1000")]
     name
     (height [(unit FOOT)]))))

Pretty printing

Pretty print the GraphQL document.

(gql/pprint my-document)
query {
  human(id: "1000") {
    name
    height(unit: FOOT)
  }
}

Alumbra

Alumbra is a very complete GraphQL library for Clojure. It provides an analyzer, a parser and Clojure Specs around GraphQL. When parsing a Grafeo GraphQL document in S-expressions format it is converted into Alumbra’s AST format.

The following example parses the GraphQL document and prints the Alumbra AST.

(binding [*print-namespace-maps* false]
  (pprint (gql/parse-document my-document)))
{:alumbra/metadata {:column 0, :row 0},
 :alumbra/operations
 [{:alumbra/metadata {:column 0, :row 0},
   :alumbra/operation-type "query",
   :alumbra/selection-set
   [{:alumbra/field-name "human",
     :alumbra/metadata {:column 0, :row 0},
     :alumbra/arguments
     [{:alumbra/argument-name "id",
       :alumbra/argument-value
       {:alumbra/metadata {:column 0, :row 0},
        :alumbra/string "1000",
        :alumbra/value-type :string},
       :alumbra/metadata {:column 0, :row 0}}],
     :alumbra/selection-set
     [{:alumbra/field-name "name",
       :alumbra/metadata {:column 0, :row 0}}
      {:alumbra/field-name "height",
       :alumbra/metadata {:column 0, :row 0},
       :alumbra/arguments
       [{:alumbra/argument-name "unit",
         :alumbra/argument-value
         {:alumbra/enum "FOOT",
          :alumbra/metadata {:column 0, :row 0},
          :alumbra/value-type :enum},
         :alumbra/metadata {:column 0, :row 0}}]}]}]}]}

JavaScript

In the JavaScript world, GraphQL clients like Apollo and Relay use a different AST format. Grafeo can translate between the Alumbra and JavaScript formats.

The following example parses the GraphQL document and prints the JavaScript AST.

(pprint (gql/parse-document-js my-document))
{:definitions
 [{:directives [],
   :kind "OperationDefinition",
   :loc {:startToken {:column 0, :line 0, :start nil}},
   :name nil,
   :operation "query",
   :selectionSet
   {:kind "SelectionSet",
    :selections
    [{:alias nil,
      :arguments
      [{:kind "Argument",
        :loc {:startToken {:column 0, :line 0, :start nil}},
        :name
        {:kind "Name",
         :loc {:startToken {:column 0, :line 0, :start nil}},
         :value "id"},
        :value
        {:block false,
         :kind "StringValue",
         :loc {:startToken {:column 0, :line 0, :start nil}},
         :value "1000"}}],
      :directives [],
      :kind "Field",
      :loc {:startToken {:column 0, :line 0, :start nil}},
      :name
      {:kind "Name",
       :loc {:startToken {:column 0, :line 0, :start nil}},
       :value "human"},
      :selectionSet
      {:kind "SelectionSet",
       :selections
       [{:alias nil,
         :arguments [],
         :directives [],
         :kind "Field",
         :loc {:startToken {:column 0, :line 0, :start nil}},
         :name
         {:kind "Name",
          :loc {:startToken {:column 0, :line 0, :start nil}},
          :value "name"},
         :selectionSet nil}
        {:alias nil,
         :arguments
         [{:kind "Argument",
           :loc {:startToken {:column 0, :line 0, :start nil}},
           :name
           {:kind "Name",
            :loc {:startToken {:column 0, :line 0, :start nil}},
            :value "unit"},
           :value
           {:kind "EnumValue",
            :loc {:startToken {:column 0, :line 0, :start nil}},
            :value "FOOT"}}],
         :directives [],
         :kind "Field",
         :loc {:startToken {:column 0, :line 0, :start nil}},
         :name
         {:kind "Name",
          :loc {:startToken {:column 0, :line 0, :start nil}},
          :value "height"},
         :selectionSet nil}]}}]},
   :variableDefinitions []}],
 :kind "Document",
 :loc {:startToken {:column 0, :line 0, :start nil}}}

HTTP Client

Grafeo provides a clj-http based HTTP client for GraphQL. The following example show how to query a GraphQL based server. Start the SWAPI server in this repository on http://localhost:4000/graphql.

node server.js

Require the HTTP client.

(require '[grafeo.http :as http])

Define the server we are talking to.

(def my-server
  {:scheme :http
   :server-name "localhost"
   :server-port 4000})

Query the local Star Wars API server and print the result.

(->> (http/request my-server my-document) :body pprint)
{:data {:human {:name "Luke Skywalker", :height 5.6430448}}}

With variables.

(->> (http/request
      my-server
      '((query
         HeroNameAndFriends
         [($episode Episode)]
         (hero
          [(episode $episode)]
          name
          (friends name))))
      {:variables {:episode "JEDI"}})
     :body pprint)
{:data
 {:hero
  {:name "R2-D2",
   :friends
   [{:name "Luke Skywalker"}
    {:name "Han Solo"}
    {:name "Leia Organa"}]}}}

License

Copyright © 2019 r0man

Distributed under the Eclipse Public License, the same as Clojure.

About

A GraphQL document and schema language based on S-expressions in Clojure & ClojureScript

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published