Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/r0man/grafeo

A GraphQL document and schema language based on S-expressions in Clojure & ClojureScript
https://github.com/r0man/grafeo

alumbra clojure clojurescript dsl graphql lisp

Last synced: 3 months ago
JSON representation

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

Awesome Lists containing this project

README

        

* Grafeo

#+author: r0man
#+LANGUAGE: en

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

/Grafeo/ is [[https://clojure.org][Clojure]] and [[https://github.com/clojure/clojurescript][ClojureScript]] library that provides a
S-expression based language for [[https://graphql.org/][GraphQL]] documents and schemas.

** Usage

Require the library.

#+BEGIN_SRC clojure :exports code :results silent
(require '[clojure.pprint :refer [pprint]])
(require '[grafeo.core :as gql])
#+END_SRC

Define a GraphQL document in s-expression format. Take a look at
the [[https://github.com/r0man/grafeo/tree/master/doc][doc]] folder to learn how to write GraphQL documents and schemas
in S-expression format.

#+BEGIN_SRC clojure :exports code :results silent
(def my-document
'((human
[(id "1000")]
name
(height [(unit FOOT)]))))
#+END_SRC

*** Pretty printing

Pretty print the GraphQL document.

#+BEGIN_SRC clojure :exports both :results output
(gql/pprint my-document)
#+END_SRC

#+RESULTS:
: query {
: human(id: "1000") {
: name
: height(unit: FOOT)
: }
: }

*** Alumbra

[[https://github.com/alumbra][Alumbra]] is a very complete GraphQL library for Clojure. It
provides an [[https://github.com/alumbra/alumbra.analyzer][analyzer]], a [[https://github.com/alumbra/alumbra.parser][parser]] and Clojure [[https://clojure.org/guides/spec][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
[[https://github.com/alumbra][Alumbra]] AST.

#+BEGIN_SRC clojure :exports both :results output
(binding [*print-namespace-maps* false]
(pprint (gql/parse-document my-document)))
#+END_SRC

#+RESULTS:
#+begin_example
{: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}}]}]}]}]}
#+end_example

*** JavaScript

In the JavaScript world, GraphQL clients like [[https://www.apollographql.com/docs/react/][Apollo]] and [[https://facebook.github.io/relay/][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.

#+BEGIN_SRC clojure :exports both :results output
(pprint (gql/parse-document-js my-document))
#+END_SRC

#+RESULTS:
#+begin_example
{: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}}}
#+end_example

*** HTTP Client

/Grafeo/ provides a [[https://github.com/dakrone/clj-http][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][http://localhost:4000/graphql]].

#+BEGIN_SRC clojure :exports both :results silent
node server.js
#+END_SRC

Require the HTTP client.

#+BEGIN_SRC clojure :exports both :results silent
(require '[grafeo.http :as http])
#+END_SRC

Define the server we are talking to.

#+BEGIN_SRC clojure :exports both :results silent
(def my-server
{:scheme :http
:server-name "localhost"
:server-port 4000})
#+END_SRC

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

#+BEGIN_SRC clojure :exports both :results output
(->> (http/request my-server my-document) :body pprint)
#+END_SRC

#+RESULTS:
: {:data {:human {:name "Luke Skywalker", :height 5.6430448}}}

With variables.

#+BEGIN_SRC clojure :exports both :results output
(->> (http/request
my-server
'((query
HeroNameAndFriends
[($episode Episode)]
(hero
[(episode $episode)]
name
(friends name))))
{:variables {:episode "JEDI"}})
:body pprint)
#+END_SRC

#+RESULTS:
: {:data
: {:hero
: {:name "R2-D2",
: :friends
: [{:name "Luke Skywalker"}
: {:name "Han Solo"}
: {:name "Leia Organa"}]}}}

** License

Copyright © 2019 [[https://github.com/r0man][r0man]]

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