GraphQL in Clojure data structures, Hiccup style.
hicgql
is in Clojars. Just add it.
[io.github.timrichardt/hicgql "0.3.0"]
io.github.timrichardt/hicgql {:mvn/version "0.3.0"}
(:require
[hicgql.core :refer [graphql]])
GraphQL documents are described with nested vectors, where the first element of each vector is a keyword describing the type of the document element.
[:<ELEMENT-TYPE> :<PROPS?> :<CHILD? OR CHILDREN?>]
hicgql.core/graphql
accepts an arbitrary number of operations and renders them concatenated with a\n
inbetween.
Operations are described with :*/
namespaced keywords, e.g. :*/OperationName
. Valid types are :query
, :mutation
, subscription
, and can be set via :*/type
. Variables are supplied as :$var "Type"
pairs.
(graphql
[:*/Op {:*/type :query
:$var "Type"
:$var2 ["Type2" "default-value"]} :id])
query Op($var: Type, $var2: Type2 = "default-value") {
id
}
Fields with subfields are prefixed by :+/
namespace. Data fields without subfields do not have a namespace.
[:+/fieldWithSubfields
:subfield1
:subfield2
:.../fragment
[:+/anotherSubfieldedField
:andSoOn]]
{
fieldWithSubfields {
subfield1
subfield2
...fragment
anotherSubfieldedField {
andSoOn
}
}
}
Arguments to fields can be set with a map which is the second element of the selection vector. Argument names are the keys, the values can be clojure data structures that can be meaningfully translated with
js/JSON.stringify
or cheshire.core/generate-string
.
[:+/_
[:fieldWithArgs {:stringArg "string"
:numberArg 2
:objArg {:size [27.32 "cm"]}}]]
{
fieldWithArgs(stringArg: "string", numberArg: 2, objArg: {size: [27.32 "cm"]})
}
To define a GraphQL document, that does not start with an operation, there is :+/_
: [:+/_ field]
→ { field }
.
Directives can be set with the :!
key in the property map. !:
's value has to be a list of directives. A directive is either a key :directive
→ @directive
, or can be supplied with arguments, like a field.
[:+/_
[:fieldWithDirs {:! [[:dir2 {:arg1 :$var
:arg2 'VAL}]
:dir1]}]]
{
fieldWithDirs @dir2(arg1: $var, arg2: VAL) @dir1
}
Directives are applied from bottom to top.
Aliases can be set with the :>/
namespace. The name
of the keyword is the name of the aliased field.
[:+/_
[:>/alias [:someField {:arg "val"}]]]
{
alias: someField(arg: "val")
}
Inline fragments are defined with :?/
prefixed keywords. The name
of the keyword has to be the type the fragment is of.
[:+/_
[:?/TypeA :id]]
{
... on TypeA {
id
}
}
Fragments are defined as operations, but with :§/
namespaced keywords. The fragment type has to be set via the :on
property.
[:§/Fragment {:on :Type}
:field]
fragment Fragment on Type {
field
}
It is possible, to use for example for
, to generate a list of fields.
[:+/_
(for [m ["M" "N"]]
(for [a ["A" "B" "C"]
x ["X" "Y" "Z"]]
(keyword (str a x m))))]
{AXM,AYM,AZM,BXM,BYM,BZM,CXM,CYM,CZM,AXN,AYN,AZN,BXN,
BYN,BZN,CXN,CYN,CZN,AXP,AYP,AZP,BXP,BYP,BZP,CXP,CYP,CZP}
re-graph
re-graph
adds the operation type on it's own, so you must not supply the *:/type
keyword to the property map.
(re-graph/query
:query-id
(graphql
[:*/MyQuery {:$var "String"}
[:+/selection {:arg :$var}
:subfield]])
{:var "value"}
callback)
Eclipse Public License https://www.eclipse.org/legal/epl-v10.html
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close