diff --git a/src/datahike/api/specification.cljc b/src/datahike/api/specification.cljc index b16e0eed..1328bdba 100644 --- a/src/datahike/api/specification.cljc +++ b/src/datahike/api/specification.cljc @@ -8,22 +8,26 @@ [name] (.replace (str name) "?" "")) -(defn spec-args->argslist [args] - (if-not (seq? args) - args - (cond (= (first args) 's/cat) - [[(symbol (name (second args)))]] - - (= (first args) 's/alt) - (mapv (fn [s] - (if (= s :nil) - [] - [(symbol (name s))])) - (take-nth 2 (rest args)))))) - -(comment - (spec-args->argslist '(s/alt :config (s/cat :config spec/SConfig) - :nil (s/cat)))) +(defn spec-args->argslist + "This function is a helper to translate a spec into a list of arguments. It is only complete enough to deal with the specs in this namespace." + [s] + (if-not (seq? s) + (if (= :nil s) [] [(symbol (name s))]) + (let [[op & args] s] + (cond + (= op 's/cat) + [(vec (mapcat (fn [[k v]] + (if (and (seq? v) (= (first v) 's/*)) + (vec (concat ['&] (spec-args->argslist k))) + (spec-args->argslist k))) + (partition 2 args)))] + + (= op 's/alt) + (vec (mapcat (fn [[_k v]] + (spec-args->argslist v)) + (partition 2 args))) + :else + [])))) (def api-specification '{database-exists? diff --git a/test/datahike/test/specification_test.cljc b/test/datahike/test/specification_test.cljc new file mode 100644 index 00000000..3612c478 --- /dev/null +++ b/test/datahike/test/specification_test.cljc @@ -0,0 +1,22 @@ +(ns datahike.test.specification-test + (:require + #?(:cljs [cljs.test :as t :refer-macros [is are deftest testing]] + :clj [clojure.test :as t :refer [is are deftest testing]]) + [datahike.api.specification :refer [spec-args->argslist]])) + +(deftest spec-to-argslist-translation + (testing "Testing core cases of spec to argslist translator." + (is (= (spec-args->argslist '(s/alt :config (s/cat :config spec/SConfig) + :nil (s/cat))) + '[[config] []])) + + (is (= (spec-args->argslist '(s/cat :conn spec/SConnection :txs spec/STransactions)) + '[[conn txs]])) + + (is (= (spec-args->argslist '(s/alt :argmap (s/cat :map spec/SQueryArgs) + :with-params (s/cat :q (s/or :vec vector? :map map?) :args (s/* any?)))) + '[[map] [q & args]])) + + (is (= (spec-args->argslist '(s/alt :simple (s/cat :db spec/SDB :opts spec/SPullOptions) + :full (s/cat :db spec/SDB :selector coll? :eid spec/SEId))) + '[[db opts] [db selector eid]]))))