mirror of
https://github.com/penpot/penpot.git
synced 2025-05-12 19:36:37 +02:00
✨ Improve dispatcher impl usability.
This commit is contained in:
parent
761a3c102f
commit
45cc4e0d27
1 changed files with 49 additions and 15 deletions
|
@ -16,9 +16,9 @@
|
||||||
[uxbox.util.spec :as us]
|
[uxbox.util.spec :as us]
|
||||||
[uxbox.util.exceptions :as ex])
|
[uxbox.util.exceptions :as ex])
|
||||||
(:import
|
(:import
|
||||||
|
clojure.lang.IDeref
|
||||||
|
clojure.lang.MapEntry
|
||||||
java.util.Map
|
java.util.Map
|
||||||
java.util.List
|
|
||||||
java.util.Map$Entry
|
|
||||||
java.util.HashMap))
|
java.util.HashMap))
|
||||||
|
|
||||||
(definterface IDispatcher
|
(definterface IDispatcher
|
||||||
|
@ -27,9 +27,15 @@
|
||||||
(deftype Dispatcher [reg attr interceptors]
|
(deftype Dispatcher [reg attr interceptors]
|
||||||
IDispatcher
|
IDispatcher
|
||||||
(add [this key f metadata]
|
(add [this key f metadata]
|
||||||
(.put ^Map reg key (Map/entry f metadata))
|
(.put ^Map reg key (MapEntry/create f metadata))
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
|
clojure.lang.IDeref
|
||||||
|
(deref [_]
|
||||||
|
{:registry reg
|
||||||
|
:attr attr
|
||||||
|
:interceptors interceptors})
|
||||||
|
|
||||||
clojure.lang.IFn
|
clojure.lang.IFn
|
||||||
(invoke [_ params]
|
(invoke [_ params]
|
||||||
(let [key (get params attr)
|
(let [key (get params attr)
|
||||||
|
@ -38,8 +44,8 @@
|
||||||
(p/rejected (ex/error :type :not-found
|
(p/rejected (ex/error :type :not-found
|
||||||
:code :method-not-found
|
:code :method-not-found
|
||||||
:hint "No method found for the current request."))
|
:hint "No method found for the current request."))
|
||||||
(let [f (.getKey ^Map$Entry entry)
|
(let [f (.key ^MapEntry entry)
|
||||||
m (.getValue ^Map$Entry entry)
|
m (.val ^MapEntry entry)
|
||||||
d (p/deferred)]
|
d (p/deferred)]
|
||||||
|
|
||||||
(sp/execute (conj interceptors f)
|
(sp/execute (conj interceptors f)
|
||||||
|
@ -57,25 +63,53 @@
|
||||||
`(defonce ~sname (Dispatcher. (HashMap.)
|
`(defonce ~sname (Dispatcher. (HashMap.)
|
||||||
~dispatch-by
|
~dispatch-by
|
||||||
~interceptors)))
|
~interceptors)))
|
||||||
|
(defn parse-defmethod
|
||||||
|
[args]
|
||||||
|
(loop [r {}
|
||||||
|
s 0
|
||||||
|
v (first args)
|
||||||
|
n (rest args)]
|
||||||
|
(case s
|
||||||
|
0 (if (symbol? v)
|
||||||
|
(recur (assoc r :sym v) 1 (first n) (rest n))
|
||||||
|
(throw (ex-info "first arg to `defmethod` should be a symbol" {})))
|
||||||
|
1 (if (qualified-keyword? v)
|
||||||
|
(recur (-> r
|
||||||
|
(assoc :key (keyword (name v)))
|
||||||
|
(assoc :meta {:spec v :doc nil}))
|
||||||
|
3 (first n) (rest n))
|
||||||
|
(recur r (inc s) v n))
|
||||||
|
2 (if (simple-keyword? v)
|
||||||
|
(recur (-> r
|
||||||
|
(assoc :key v)
|
||||||
|
(assoc :meta {:doc nil}))
|
||||||
|
3 (first n) (rest n))
|
||||||
|
(throw (ex-info "second arg to `defmethod` should be a keyword" {})))
|
||||||
|
3 (if (string? v)
|
||||||
|
(recur (update r :meta assoc :doc v) (inc s) (first n) (rest n))
|
||||||
|
(recur r 4 v n))
|
||||||
|
4 (if (map? v)
|
||||||
|
(recur (update r :meta merge v) (inc s) (first n) (rest n))
|
||||||
|
(recur r 5 v n))
|
||||||
|
5 (if (vector? v)
|
||||||
|
(assoc r :args v :body n)
|
||||||
|
(throw (ex-info "missing arguments vector" {}))))))
|
||||||
|
|
||||||
(defmacro defmethod
|
(defmacro defmethod
|
||||||
[sname key metadata args & rest]
|
[& args]
|
||||||
(s/assert symbol? sname)
|
(let [{:keys [key meta sym args body]} (parse-defmethod args)
|
||||||
(s/assert keyword? key)
|
f `(fn ~args ~@body)]
|
||||||
(s/assert map? metadata)
|
|
||||||
(s/assert vector? args)
|
|
||||||
(let [f `(fn ~args ~@rest)]
|
|
||||||
`(do
|
`(do
|
||||||
(s/assert dispatcher? ~sname)
|
(s/assert dispatcher? ~sym)
|
||||||
(.add ~sname ~key ~f ~metadata)
|
(.add ~sym ~key ~f ~meta)
|
||||||
~sname)))
|
~sym)))
|
||||||
|
|
||||||
(def spec-interceptor
|
(def spec-interceptor
|
||||||
"An interceptor that conforms the request with the user provided
|
"An interceptor that conforms the request with the user provided
|
||||||
spec."
|
spec."
|
||||||
{:enter (fn [{:keys [request] :as data}]
|
{:enter (fn [{:keys [request] :as data}]
|
||||||
(let [{:keys [spec]} (meta request)]
|
(let [{:keys [spec]} (meta request)]
|
||||||
(if spec
|
(if-let [spec (s/get-spec spec)]
|
||||||
(let [result (s/conform spec request)]
|
(let [result (s/conform spec request)]
|
||||||
(if (not= result ::s/invalid)
|
(if (not= result ::s/invalid)
|
||||||
(assoc data :request result)
|
(assoc data :request result)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue