Skip to content

Instantly share code, notes, and snippets.

Last active March 5, 2018 23:24
What would you like to do? query spec
(:require [cljs.spec :as s]))
(s/def ::ident (s/and vector? (s/cat :ident keyword? :value #(not (coll? %)))))
(s/def ::join-key (s/or :prop keyword? :ident ::ident))
(s/def ::join (s/and (s/map-of ::join-key ::query) #(= (count %) 1)))
(s/def ::union (s/and (s/map-of keyword? ::query) #(> (count %) 1)))
(s/def ::param-expr
(s/cat :query-expr ::query-expr
:params map?))
(s/def ::mutation-expr
(s/or :no-params (s/cat :mutate-key symbol?)
:with-params (s/cat :mutate-key symbol?
:params map?)))
(s/def ::query-expr
(s/or :prop keyword?
:ident ::ident
:mutation-expr ::mutation-expr
:union ::union
:param-expr ::join))
(s/def ::query
(s/or :recursion (s/or :depth number?
:unbounded #(= % '...))
:query (s/and vector?
(s/+ ::query-expr))))
(s/explain ::query '[:name {:friend "foo"}])
; val: [:name {:friend "foo"}] fails at: [:recursion :depth] predicate: number?
; val: [:name {:friend "foo"}] fails at: [:recursion :unbounded] predicate: (= % (quote ...))
; In: [1] val: ({:friend "foo"}) fails at: [:query] predicate: (cat :_ (*, Extra input
Copy link

devth commented Feb 20, 2017

This is incomplete right? Did you run into any blocking issues preventing fully specing out queries?

Copy link

devth commented Feb 21, 2017

For example, this union query is not valid with the above specs.

[{:items/list {:foo [:item/id :item/type :foo/value]
               :bar [:item/id :item/type :bar/value]}}]

If you make a few changes, it works:

(s/def ::join (s/map-of ::join-key ::query))
(s/def ::union (s/map-of keyword? (s/map-of keyword? ::query)))

Copy link

#(= % '...) => #{'...}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment