(def machine
(fsm/machine
{:id ::traffic
:initial :red
:states {:red {:on {::tick :green}}
:green {:on {::tick :orange}}
:orange {:on {::tick :red}}}}))
(defn statechart->interceptor
[{:keys [id path machine]}]
(rf/->interceptor
:id id
:before (fn [context]
(let [eid (get-in context [:coeffects :event 0])
s0 (or (get-in context (into [:coeffects :db] path))
(fsm/initialize m))]
(try (let [s1 (fsm/transition machine (assoc s0 :fx [] :context context) {:type eid})]
(assoc-in context [:coeffects id] (dissoc s1 :context)))
(catch js/Object err
(js/console.warn (ex-info ::fsm.error {:id id :s0 s0 :eid eid} err))
context))))
:after (fn [context]
(if-let [s1 (get-in context [:coeffects id])]
(let [db (or (get-in context [:effects :db])
(get-in context [:coeffects :db]))
fx (get-in context [:effects :fx] [])]
(-> context
(update :coeffects dissoc id)
(assoc-in [:effects :db] (assoc-in db path (dissoc s1 :fx)))
(assoc-in [:effects :fx] (into fx (:fx s1)))))
context))))
(rf/clear-global-interceptor ::fsm-id)
(rf/reg-global-interceptor (statechart->interceptor {:id ::fsm-id :machine machine :path [:fsm/state]}))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment