[dev feature] extend the defn macro

the defn macro knows register the function as an events under the
keywords provided in the :events key of the attributes map. It also
adds the interceptors provided in the :interceptors map

exemple:

```clojure
(fx/defn hello4
  {:doc "this function is useless as well"
   :events [:test/valid1 :test/valid2]}
  [{:keys [db]} b]
  {:db (assoc db :a b) :b (:a db)})
```

Signed-off-by: yenda <eric@status.im>
This commit is contained in:
yenda 2019-05-23 17:30:47 +02:00
parent 64afaf5eb3
commit 9b04dc6530
No known key found for this signature in database
GPG Key ID: 0095623C0069DCE6
5 changed files with 61 additions and 25 deletions

View File

@ -90,7 +90,23 @@
(transactions/initialize) (transactions/initialize)
(ethereum.subscriptions/initialize))) (ethereum.subscriptions/initialize)))
(fx/defn user-login [{:keys [db] :as cofx} create-database?] (fx/defn user-login-without-creating-db
{:events [:accounts.login.ui/password-input-submitted]}
[{:keys [db] :as cofx}]
(let [{:keys [address password]} (accounts.db/credentials cofx)]
(fx/merge
cofx
{:db (-> db
(assoc-in [:accounts/login :processing] true)
(assoc :node/on-ready :login))
:accounts.login/clear-web-data nil
:data-store/change-account [address
password
false
(get-in db [:accounts/accounts address :settings :fleet])]})))
(fx/defn user-login
[{:keys [db] :as cofx} create-database?]
(let [{:keys [address password]} (accounts.db/credentials cofx)] (let [{:keys [address password]} (accounts.db/credentials cofx)]
(fx/merge (fx/merge
cofx cofx
@ -120,6 +136,11 @@
:dispatch [:accounts.logout.ui/logout-confirmed]})) :dispatch [:accounts.logout.ui/logout-confirmed]}))
(fx/defn user-login-callback (fx/defn user-login-callback
{:events [:accounts.login.callback/login-success]
:interceptors [(re-frame/inject-cofx :web3/get-web3)
(re-frame/inject-cofx :data-store/get-all-mailservers)
(re-frame/inject-cofx :data-store/transport)
(re-frame/inject-cofx :data-store/mailserver-topics)]}
[{:keys [db web3] :as cofx} login-result] [{:keys [db web3] :as cofx} login-result]
(let [data (types/json->clj login-result) (let [data (types/json->clj login-result)
error (:error data) error (:error data)

View File

@ -308,20 +308,6 @@
;; accounts login module ;; accounts login module
(handlers/register-handler-fx
:accounts.login.ui/password-input-submitted
(fn [cofx _]
(accounts.login/user-login cofx false)))
(handlers/register-handler-fx
:accounts.login.callback/login-success
[(re-frame/inject-cofx :web3/get-web3)
(re-frame/inject-cofx :data-store/get-all-mailservers)
(re-frame/inject-cofx :data-store/transport)
(re-frame/inject-cofx :data-store/mailserver-topics)]
(fn [cofx [_ login-result]]
(accounts.login/user-login-callback cofx login-result)))
(handlers/register-handler-fx (handlers/register-handler-fx
:accounts.login.callback/verify-success :accounts.login.callback/verify-success
(fn [cofx [_ verify-result realm-error]] (fn [cofx [_ verify-result realm-error]]

View File

@ -247,7 +247,7 @@
[:navigation/screen-params :tribute-to-talk :state] [:navigation/screen-params :tribute-to-talk :state]
:transaction-failed)}))) :transaction-failed)})))
(defn remove (fx/defn remove
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(fx/merge cofx (fx/merge cofx
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk] {:db (assoc-in db [:navigation/screen-params :tribute-to-talk]

View File

@ -1,6 +1,15 @@
(ns status-im.utils.fx (ns status-im.utils.fx
(:refer-clojure :exclude [defn])) (:refer-clojure :exclude [defn]))
(defn- register-events
[events interceptors name args]
(mapv (fn [event]
`(status-im.utils.handlers/register-handler-fx
~event
~interceptors
(fn [cofx# [_# ~@args]] (~name cofx# ~@args))))
events))
(defmacro defn (defmacro defn
"Defines an fx producing function "Defines an fx producing function
Takes the same arguments as the defn macro Takes the same arguments as the defn macro
@ -12,7 +21,8 @@
Notes: Notes:
- destructuring of cofx is possible - destructuring of cofx is possible
- supports docstring - supports docstring
- supports attr-map - supports attr-map with optional :events key which needs to be a vector of
event keywords under which the function will be registered
- TODO: add suport for `prepost-map?` (don't forget to add it to arglist) - TODO: add suport for `prepost-map?` (don't forget to add it to arglist)
- TODO: add validation of macro parameters" - TODO: add validation of macro parameters"
{:arglists '([name doc-string? attr-map? [params*] body])} {:arglists '([name doc-string? attr-map? [params*] body])}
@ -26,17 +36,24 @@
m (if (map? (first fdecl)) m (if (map? (first fdecl))
(conj m (first fdecl)) (conj m (first fdecl))
m) m)
events (get m :events [])
interceptors (get m :interceptors [])
fdecl (if (map? (first fdecl)) fdecl (if (map? (first fdecl))
(next fdecl) (next fdecl)
fdecl) fdecl)
[cofx & args] (first fdecl) [cofx & args] (first fdecl)
fdecl (next fdecl) fdecl (next fdecl)
argsyms (take (count args) (repeatedly #(gensym "arg")))] argsyms (take (count args) (repeatedly #(gensym "arg")))]
`(clojure.core/defn ~(with-meta name m) (if (and (sequential? events)
([~@argsyms] (fn [cofx#] (~name cofx# ~@argsyms))) (every? keyword? events))
`(do
(clojure.core/defn ~(with-meta name m)
([~@argsyms] (fn [cofx#] (~(with-meta name m) cofx# ~@argsyms)))
([cofx# ~@args] ([cofx# ~@args]
(if (and (map? cofx#) (if (and (map? cofx#)
(not (nil? (:db cofx#)))) (not (nil? (:db cofx#))))
(let [~cofx cofx#] (let [~cofx cofx#]
~@fdecl) ~@fdecl)
(throw (js/Error. (str "fx/defn expects a map of cofx as first argument got " cofx# " in function " ~name)))))))) (throw (js/Error. (str "fx/defn expects a map of cofx as first argument got " cofx# " in function " ~name))))))
~@(register-events events interceptors (with-meta name m) args))
(throw (Exception. (str "fx/defn expects a vector of keyword as value for :events key in attr-map in function " name))))))

View File

@ -17,6 +17,18 @@
[{:keys [db]} b] [{:keys [db]} b]
(identity nil)) (identity nil))
(fx/defn hello4
{:doc "this function is useless as well"
:events [:test/valid1 :test/valid2]}
[{:keys [db]} b]
{:db (assoc db :a b) :b (:a db)})
(fx/defn hello5
"lol lazy function does nothing"
{:events [:test]}
[{:keys [db]} b]
(identity nil))
(deftest merge-fxs-test (deftest merge-fxs-test
(testing "merge function for fxs" (testing "merge function for fxs"
(let [cofx {:db {:c 2}}] (let [cofx {:db {:c 2}}]