(ns om.next.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/map-of ::join-key ::query)) (s/def ::union (s/map-of keyword? (s/map-of keyword? ::query))) (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)))) (comment (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 :_ (* :om.next.spec/query-expr)), Extra input )