diff --git a/modules/reitit-core/src/reitit/coercion.cljc b/modules/reitit-core/src/reitit/coercion.cljc index ef35ac14..57d55628 100644 --- a/modules/reitit-core/src/reitit/coercion.cljc +++ b/modules/reitit-core/src/reitit/coercion.cljc @@ -17,8 +17,7 @@ (-open-model [this model] "Returns a new model which allows extra keys in maps") (-encode-error [this error] "Converts error in to a serializable format") (-request-coercer [this type model] "Returns a `value format => value` request coercion function") - (-response-coercer [this model] "Returns a `value format => value` response coercion function") - (-route-data-merge [this acc k v])) + (-response-coercer [this model] "Returns a `value format => value` response coercion function")) #?(:clj (defmethod print-method ::coercion [coercion ^Writer w] diff --git a/modules/reitit-core/src/reitit/impl.cljc b/modules/reitit-core/src/reitit/impl.cljc index 65554238..181eae9b 100644 --- a/modules/reitit-core/src/reitit/impl.cljc +++ b/modules/reitit-core/src/reitit/impl.cljc @@ -9,6 +9,9 @@ (:import (java.util HashMap Map) (java.net URLEncoder URLDecoder)))) +(defprotocol RouteDataMerge + (-route-data-merge [this acc k v])) + (defn parse [path opts] (let [path #?(:clj (.intern ^String (trie/normalize path opts)) :cljs (trie/normalize path opts)) path-parts (trie/split-path path opts) @@ -67,13 +70,15 @@ (let [;; Find last the effective :coercion value ;; for the route, and then use the cocercion ;; instance for route data merge implementation. + ;; TODO: other options/keys should also be able to control + ;; merge? coercion (->> x reverse (some (fn [[k v]] (when (= :coercion k) v)))) route-data-merge (if coercion - #((resolve 'reitit.coercion/-route-data-merge) coercion %1 %2 %3) + #(-route-data-merge coercion %1 %2 %3) default-route-data-merge)] (reduce (fn [acc [k v]] @@ -85,8 +90,7 @@ x))) (defn resolve-routes [raw-routes {:keys [coerce] :as opts}] - (cond->> (->> (walk raw-routes opts) - (map-data merge-data)) + (cond->> (->> (walk raw-routes opts) (map-data merge-data)) coerce (into [] (keep #(coerce % opts))))) (defn path-conflicting-routes [routes opts] diff --git a/modules/reitit-malli/src/reitit/coercion/malli.cljc b/modules/reitit-malli/src/reitit/coercion/malli.cljc index 3a12531b..a3a9ec26 100644 --- a/modules/reitit-malli/src/reitit/coercion/malli.cljc +++ b/modules/reitit-malli/src/reitit/coercion/malli.cljc @@ -8,7 +8,7 @@ [malli.core :as m] [clojure.set :as set] [clojure.walk :as walk] - [meta-merge.core :as mm])) + [reitit.impl :as impl])) ;; ;; coercion @@ -181,9 +181,10 @@ (-coercer (compile schema options) type transformers :decode opts)) (-response-coercer [_ schema] (-coercer (compile schema options) :response transformers :encode opts)) + impl/RouteDataMerge (-route-data-merge [_ acc k v] (case k :parameters (assoc acc :parameters (merge-with mu/merge (:parameters acc) v)) - (mm/meta-merge acc {k v}))))))) + (impl/default-route-data-merge acc k v))))))) (def coercion (create default-options)) diff --git a/modules/reitit-schema/src/reitit/coercion/schema.cljc b/modules/reitit-schema/src/reitit/coercion/schema.cljc index 2a31f123..0b252d5d 100644 --- a/modules/reitit-schema/src/reitit/coercion/schema.cljc +++ b/modules/reitit-schema/src/reitit/coercion/schema.cljc @@ -96,6 +96,7 @@ (-response-coercer [this schema] (if (coerce-response? schema) (coercion/-request-coercer this :response schema))) + impl/RouteDataMerge (-route-data-merge [this acc k v] (impl/default-route-data-merge acc k v)))) diff --git a/modules/reitit-spec/src/reitit/coercion/spec.cljc b/modules/reitit-spec/src/reitit/coercion/spec.cljc index 8e19f4db..729fb46a 100644 --- a/modules/reitit-spec/src/reitit/coercion/spec.cljc +++ b/modules/reitit-spec/src/reitit/coercion/spec.cljc @@ -137,6 +137,7 @@ (-response-coercer [this spec] (if (coerce-response? spec) (coercion/-request-coercer this :response spec))) + impl/RouteDataMerge (-route-data-merge [this acc k v] (impl/default-route-data-merge acc k v)))) diff --git a/test/cljc/reitit/impl_test.cljc b/test/cljc/reitit/impl_test.cljc index cc0405c0..626d742e 100644 --- a/test/cljc/reitit/impl_test.cljc +++ b/test/cljc/reitit/impl_test.cljc @@ -190,25 +190,27 @@ [:view 'b] [:controllers ^:replace [2]]]))) - (is (= {:a schema/Str - :b schema/Str} - (-> (impl/merge-data "/" - [[:parameters {:path {:a schema/Str}}] - [:parameters {:path {:b schema/Str}}]]) - :parameters - :path))) + (testing "Schema - regular merge" + (is (= {:a schema/Str + :b schema/Str} + (-> (impl/merge-data "/" + [[:parameters {:path {:a schema/Str}}] + [:parameters {:path {:b schema/Str}}]]) + :parameters + :path)))) - (is (= [:map - [:a 'string?] - [:b 'int?]] - (-> (impl/merge-data "/" - [[:coercion rcm/coercion] - [:parameters {:path [:map [:a 'string?]]}] - [:parameters {:path [:map [:b 'int?]]}]]) - :parameters - :path - ;; Merge returns schema object, convert back to form for comparison - malli.core/form))) + (testing "Malli schema merge - mu/merge" + (is (= [:map + [:a 'string?] + [:b 'int?]] + (-> (impl/merge-data "/" + [[:coercion rcm/coercion] + [:parameters {:path [:map [:a 'string?]]}] + [:parameters {:path [:map [:b 'int?]]}]]) + :parameters + :path + ;; Merge returns schema object, convert back to form for comparison + malli.core/form)))) - ;; TODO: Also test and support Schema and spec merging + ;; TODO: Spec )