Fork me on GitHub
#clojure-spec
<
2023-02-28
>
stopa18:02:39

Hey team! I am making a graphql-like query language, that looks something like this:

{"users" {"$" {"where" {"bookshelves.books.title" "The Count of Monte Cristo"}}
          "bookshelves" {}}
 "books" {}}
Here, I have forms, which have an option-map , and further children. What I would want here is a combination of keys (to say what $ should be), and map-of, to describe that it can have children. I wasn't sure how to do this, so the best approach I could think of, was to massage the data into a kind of vector, like:
[["users", {"where" {"bookshelves.books.title" "The Count of Monte Cristo"}}, ["bookshelves", {}, []]], 
 ["books", {}, []]]
So then I could type this vec, like so:
(s/def ::where (s/map-of string? ::triple-model/value))

(s/def ::option-map (s/keys :opt-un [::where]))

(s/def ::form (s/cat
               :k string?
               :option-map ::option-map
               :children (s/coll-of ::inner-form)))

(s/def ::forms (s/coll-of ::form))
Is this the idiomatic way to do things with spec, or would you do it differently?

phronmophobic19:03:49

> I wasn't sure how to do this, so the best approach I could think of, was to massage the data into a kind of vector, like: I'm not totally sure I understand what you're trying to do, but massaging data before validation sounds like an anti-pattern.

👍 2
phronmophobic19:03:19

maybe something like:

(s/def ::options (s/keys))
(s/def ::form
  (s/coll-of
   (s/or
    :options (s/tuple #{"$"}
                      ::options)
    :sub-form (s/tuple string? ::form))
   :into {}))

❤️ 2
stopa15:04:41

(realized I never responded -- I think this could work! Thank you @U7RJTCH6J)

👍 2