diff --git a/modules/reitit-core/src/reitit/exception.cljc b/modules/reitit-core/src/reitit/exception.cljc index 5eb6e524..81a6c693 100644 --- a/modules/reitit-core/src/reitit/exception.cljc +++ b/modules/reitit-core/src/reitit/exception.cljc @@ -7,11 +7,14 @@ ([type data] (throw (ex-info (str type) {:type type, :data data})))) +(defn get-message [e] + #?(:clj (.getMessage ^Exception e) :cljs (ex-message e))) + (defmulti format-exception (fn [type _ _] type)) (defn exception [e] (let [data (ex-data e) - message (format-exception (:type data) #?(:clj (.getMessage ^Exception e) :cljs (ex-message e)) (:data data))] + message (format-exception (:type data) (get-message e) (:data data))] ;; there is a 3-arity version (+cause) of ex-info, but the default repl error message is taken from the cause (ex-info message (assoc (or data {}) ::cause e)))) @@ -35,3 +38,6 @@ (fn [[name vals]] (str name "\n-> " (str/join "\n-> " (mapv first vals)) "\n")) conflicts))) + +(defmethod format-exception :reitit.impl/merge-data [_ _ data] + (str "Error merging route-data\n\n" (pr-str data))) diff --git a/modules/reitit-core/src/reitit/impl.cljc b/modules/reitit-core/src/reitit/impl.cljc index 8797b77b..b2aeb250 100644 --- a/modules/reitit-core/src/reitit/impl.cljc +++ b/modules/reitit-core/src/reitit/impl.cljc @@ -4,7 +4,8 @@ [clojure.set :as set] [meta-merge.core :as mm] [reitit.trie :as trie] - [reitit.exception :as exception]) + [reitit.exception :as exception] + [reitit.exception :as ex]) #?(:clj (:import (java.util.regex Pattern) (java.util HashMap Map) @@ -58,12 +59,15 @@ (walk-one path (mapv identity data) raw-routes))) (defn map-data [f routes] - (mapv #(update % 1 f) routes)) + (mapv (fn [[p ds]] [p (f p ds)]) routes)) -(defn merge-data [x] +(defn merge-data [p x] (reduce (fn [acc [k v]] - (mm/meta-merge acc {k v})) + (try + (mm/meta-merge acc {k v}) + (catch #?(:clj Exception, :cljs js/Error) e + (ex/fail! ::merge-data {:path p, :left acc, :right {k v}, :exception e})))) {} x)) (defn resolve-routes [raw-routes {:keys [coerce] :as opts}] diff --git a/modules/reitit-dev/src/reitit/dev/pretty.cljc b/modules/reitit-dev/src/reitit/dev/pretty.cljc index fa631723..dfec05e4 100644 --- a/modules/reitit-dev/src/reitit/dev/pretty.cljc +++ b/modules/reitit-dev/src/reitit/dev/pretty.cljc @@ -335,3 +335,27 @@ problems)) (color :white "https://cljdoc.org/d/metosin/reitit/CURRENT/doc/basics/route-data-validation") [:break]]) + +(defmethod format-exception :reitit.impl/merge-data [_ _ {:keys [path left right exception]}] + [:group + (text "Error merging route-data:") + [:break] [:break] + [:group + [:span (color :grey "-- On route -----------------------")] + [:break] + [:break] + (text path) + [:break] + [:break] + [:span (color :grey "-- Exception ----------------------")] + [:break] + [:break] + (color :red (exception/get-message exception)) + [:break] + [:break] + (edn left {:margin 3}) + [:break] + (edn right {:margin 3})] + [:break] + (color :white "https://cljdoc.org/d/metosin/reitit/CURRENT/doc/basics/route-data") + [:break]]) diff --git a/test/cljc/reitit/exception_test.cljc b/test/cljc/reitit/exception_test.cljc index 971bd63d..bde403a7 100644 --- a/test/cljc/reitit/exception_test.cljc +++ b/test/cljc/reitit/exception_test.cljc @@ -43,7 +43,11 @@ ["/api/{ipa"] #"Invalid route data" - ["/api/ipa" {::roles #{:adminz}}]) + ["/api/ipa" {::roles #{:adminz}}] + + #"Error merging route-data" + ["/a" {:body {}} + ["/b" {:body [:FAIL]}]]) exception/exception pretty/exception))