mirror of
https://github.com/penpot/penpot.git
synced 2025-05-11 19:16: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.exceptions :as ex])
|
||||
(:import
|
||||
clojure.lang.IDeref
|
||||
clojure.lang.MapEntry
|
||||
java.util.Map
|
||||
java.util.List
|
||||
java.util.Map$Entry
|
||||
java.util.HashMap))
|
||||
|
||||
(definterface IDispatcher
|
||||
|
@ -27,9 +27,15 @@
|
|||
(deftype Dispatcher [reg attr interceptors]
|
||||
IDispatcher
|
||||
(add [this key f metadata]
|
||||
(.put ^Map reg key (Map/entry f metadata))
|
||||
(.put ^Map reg key (MapEntry/create f metadata))
|
||||
nil)
|
||||
|
||||
clojure.lang.IDeref
|
||||
(deref [_]
|
||||
{:registry reg
|
||||
:attr attr
|
||||
:interceptors interceptors})
|
||||
|
||||
clojure.lang.IFn
|
||||
(invoke [_ params]
|
||||
(let [key (get params attr)
|
||||
|
@ -38,8 +44,8 @@
|
|||
(p/rejected (ex/error :type :not-found
|
||||
:code :method-not-found
|
||||
:hint "No method found for the current request."))
|
||||
(let [f (.getKey ^Map$Entry entry)
|
||||
m (.getValue ^Map$Entry entry)
|
||||
(let [f (.key ^MapEntry entry)
|
||||
m (.val ^MapEntry entry)
|
||||
d (p/deferred)]
|
||||
|
||||
(sp/execute (conj interceptors f)
|
||||
|
@ -57,25 +63,53 @@
|
|||
`(defonce ~sname (Dispatcher. (HashMap.)
|
||||
~dispatch-by
|
||||
~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
|
||||
[sname key metadata args & rest]
|
||||
(s/assert symbol? sname)
|
||||
(s/assert keyword? key)
|
||||
(s/assert map? metadata)
|
||||
(s/assert vector? args)
|
||||
(let [f `(fn ~args ~@rest)]
|
||||
[& args]
|
||||
(let [{:keys [key meta sym args body]} (parse-defmethod args)
|
||||
f `(fn ~args ~@body)]
|
||||
`(do
|
||||
(s/assert dispatcher? ~sname)
|
||||
(.add ~sname ~key ~f ~metadata)
|
||||
~sname)))
|
||||
(s/assert dispatcher? ~sym)
|
||||
(.add ~sym ~key ~f ~meta)
|
||||
~sym)))
|
||||
|
||||
(def spec-interceptor
|
||||
"An interceptor that conforms the request with the user provided
|
||||
spec."
|
||||
{:enter (fn [{:keys [request] :as data}]
|
||||
(let [{:keys [spec]} (meta request)]
|
||||
(if spec
|
||||
(if-let [spec (s/get-spec spec)]
|
||||
(let [result (s/conform spec request)]
|
||||
(if (not= result ::s/invalid)
|
||||
(assoc data :request result)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue