diff --git a/src/provisdom/spectomic/core.clj b/src/provisdom/spectomic/core.clj index 95fac45..f9f5956 100644 --- a/src/provisdom/spectomic/core.clj +++ b/src/provisdom/spectomic/core.clj @@ -146,6 +146,31 @@ :att [s {}] :att-and-schema s))))) +(defn parse-spec-keys + "Given a `spec`, returns a set of keys the spec has." + [spec] + (let [form (spec-form spec) + [form-sym & form-args] form + combine-composite-specs (fn [forms] + (into #{} (mapcat parse-spec-keys) forms))] + (case form-sym + clojure.spec.alpha/keys + (->> (rest form-args) + (take-nth 2) + (flatten) + (filter keyword?) + (set)) + + (clojure.spec.alpha/merge + clojure.spec.alpha/and) + (combine-composite-specs form-args) + + + clojure.spec.alpha/or + (combine-composite-specs (->> (rest form-args) (take-nth 2))) + + nil))) + (defn datomic-schema ([specs] (datomic-schema specs nil)) ([specs {:keys [custom-type-resolver] diff --git a/test/provisdom/spectomic/core_test.clj b/test/provisdom/spectomic/core_test.clj index 408895a..87e58a6 100644 --- a/test/provisdom/spectomic/core_test.clj +++ b/test/provisdom/spectomic/core_test.clj @@ -84,6 +84,23 @@ :db/cardinality :db.cardinality/one} (spectomic/find-type-via-generation ::map nil)))) +(deftest parse-spec-keys-test + (is (= #{:a :b :c :d :e} + (spectomic/parse-spec-keys + `(s/keys :req [:a (and :b (or :c :d))] + :opt [:e])))) + (is (= #{:a :b :c} + (spectomic/parse-spec-keys + `(s/merge (s/keys :req [:a]) + (s/merge (s/keys :opt-un [:b]) + (s/keys :req [:c])))))) + (is (= #{:a :b} + (spectomic/parse-spec-keys `(s/or :a (s/keys :req [:a]) + :b (s/keys :req [:b]))))) + (is (= #{:a} + (spectomic/parse-spec-keys `(s/and (s/keys :req [:a]) + (fn [_] true)))))) + (deftest datomic-schema-test (testing "basic datomic types" (is (= [{:db/ident ::string