Skip to content

Commit

Permalink
turn public API into protocol and singleton in re-frame.core
Browse files Browse the repository at this point in the history
  • Loading branch information
martinklepsch committed Dec 20, 2016
1 parent 64a95a6 commit a38ba42
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 148 deletions.
2 changes: 1 addition & 1 deletion src/re_frame/cofx.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
;; -- Builtin CoEffects Handlers ---------------------------------------------

(defn register-built-in!
[registry]
[{:keys [app-db registry] :as frame}]
(let [register (partial reg/register-handler registry kind)]
(register
:db
Expand Down
118 changes: 41 additions & 77 deletions src/re_frame/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,20 @@
(:require
[re-frame.events :as events]
[re-frame.subs :as subs]
[re-frame.frame :as frame]
[re-frame.interop :as interop]
[re-frame.db :as db]
[re-frame.fx :as fx]
[re-frame.cofx :as cofx]
[re-frame.router :as router]
[re-frame.loggers :as loggers]
[re-frame.registrar :as registrar]
[re-frame.registry :as reg]
[re-frame.interceptor :as interceptor]
[re-frame.std-interceptors :as std-interceptors :refer [db-handler->interceptor
fx-handler->interceptor
ctx-handler->interceptor]]
fx-handler->interceptor
ctx-handler->interceptor]]
[clojure.set :as set]))


;; -- state
(def registry (reg/make-registry))
(def ev-queue (router/->EventQueue :idle interop/empty-queue {} registry))

;; -- dispatch
(def dispatch (partial router/dispatch ev-queue))
(def dispatch-sync (partial router/dispatch-sync ev-queue registry))


;; XXX move API functions up to this core level - to enable code completion and docs
;; XXX on figwheel reload, is there a way to not get the re-registration messages.


;; -- interceptor related
;; useful if you are writing your own interceptors
(def ->interceptor interceptor/->interceptor)
Expand All @@ -48,69 +34,47 @@
(def after std-interceptors/after)
(def on-changes std-interceptors/on-changes)

;; XXX move API functions up to this core level - to enable code completion and docs
;; XXX on figwheel reload, is there a way to not get the re-registration messages.

;; -- subscriptions
(defn reg-sub-raw
"Associate a given `query id` with a given subscription handler function `handler-fn`
which is expected to take two arguments: app-db and query vector, and return
a `reaction`.
This is a low level, advanced function. You should probably be using reg-sub
instead."
[query-id handler-fn]
(reg/register-handler registry subs/kind query-id handler-fn))

(def reg-sub (partial subs/reg-sub registry))
(def subscribe (partial subs/subscribe registry))

(def clear-sub (partial reg/clear-handlers registry subs/kind))
(def clear-subscription-cache! subs/clear-subscription-cache!)

;; -- effects
(def reg-fx (partial reg/register-handler registry fx/kind))
(def clear-fx (partial reg/clear-handlers registry fx/kind))
(def fx-do-fx (fx/do-fx registry))
(fx/register-built-in! registry ev-queue)

;; -- coeffects
(def reg-cofx (partial reg/register-handler registry cofx/kind))
(def inject-cofx (partial cofx/inject-cofx registry))
(def clear-cofx (partial reg/clear-handlers registry cofx/kind))
(def cofx-inject-db (cofx/inject-cofx registry :db))
(cofx/register-built-in! registry)
;; Export API wrapping `the-frame` singleton ---

(defn make-frame []
(let [registry (reg/make-registry)
event-queue (router/->EventQueue :idle interop/empty-queue {} registry)]
(frame/map->Frame
{:registry registry
:event-queue event-queue
:app-db re-frame.db/app-db
:subscriptions-cache nil})))

;; -- Events
(def clear-event (partial reg/clear-handlers registry events/kind))
(def the-frame (make-frame))

(defn reg-event-db
"Register the given `id`, typically a keyword, with the combination of
`db-handler` and an interceptor chain.
`db-handler` is a function: (db event) -> db
`interceptors` is a collection of interceptors, possibly nested (needs flattening).
`db-handler` is wrapped in an interceptor and added to the end of the chain, so in the end
there is only a chain.
The necessary effects and coeffects handler are added to the front of the
interceptor chain. These interceptors ensure that app-db is available and updated."
([id db-handler]
(reg-event-db id nil db-handler))
([id interceptors db-handler]
(events/register registry id [cofx-inject-db fx-do-fx interceptors (db-handler->interceptor db-handler)])))
(fx/register-built-in! the-frame)
(cofx/register-built-in! the-frame)

(def dispatch (partial frame/dispatch the-frame))
(def dispatch-sync (partial frame/dispatch-sync the-frame))

(defn reg-event-fx
([id fx-handler]
(reg-event-fx id nil fx-handler))
([id interceptors fx-handler]
(events/register registry id [cofx-inject-db fx-do-fx interceptors (fx-handler->interceptor fx-handler)])))
(def reg-sub-raw (partial frame/reg-sub-raw the-frame))
;; some slight weirdness here because protocols don't support variadic functions
(defn reg-sub [query-id & args]
(frame/reg-sub the-frame query-id args))
(def subscribe (partial frame/subscribe the-frame))
(def clear-sub (partial frame/clear-sub the-frame))
(def clear-subscriptions-cache! (partial frame/clear-subscriptions-cache the-frame))

(def reg-fx (partial frame/reg-fx the-frame))
(def clear-fx (partial frame/clear-fx the-frame))

(defn reg-event-ctx
([id handler]
(reg-event-ctx id nil handler))
([id interceptors handler]
(events/register registry id [cofx-inject-db fx-do-fx interceptors (ctx-handler->interceptor handler)])))
(def reg-cofx (partial frame/reg-cofx the-frame))
(def inject-cofx (partial frame/inject-cofx the-frame))
(def clear-cofx (partial frame/clear-cofx the-frame))

(def reg-event-db (partial frame/reg-event-db the-frame))
(def reg-event-fx (partial frame/reg-event-fx the-frame))
(def reg-event-ctx (partial frame/reg-event-ctx the-frame))
(def clear-event (partial frame/clear-event the-frame))

;; -- Logging -----
;; Internally, re-frame uses the logging functions: warn, log, error, group and groupEnd
Expand Down Expand Up @@ -138,8 +102,8 @@
Checkpoint includes app-db, all registered handlers and all subscriptions.
"
[]
(let [handlers (-> registry :kind->id->handler deref)
app-db @db/app-db
(let [handlers (-> the-frame :registry :kind->id->handler deref)
app-db (-> the-frame :app-db deref)
subs-cache @subs/query->reaction]
(fn []
;; call `dispose!` on all current subscriptions which
Expand All @@ -152,8 +116,8 @@
;; Reset the atoms
;; We don't need to reset subs/query->reaction, as
;; disposing of the subs removes them from the cache anyway
(reset! (:kind->id->handler registry) handlers)
(reset! db/app-db app-db)
(reset! (-> the-frame :registry :kind->id->handler) handlers)
(reset! (-> the-frame :app-db) app-db)
nil)))


Expand All @@ -177,12 +141,12 @@
([f]
(add-post-event-callback f f)) ;; use f as its own identifier
([id f]
(router/add-post-event-callback ev-queue id f)))
(router/add-post-event-callback (:event-queue the-frame) id f)))


(defn remove-post-event-callback
[id]
(router/remove-post-event-callback ev-queue id))
(router/remove-post-event-callback (:event-queue the-frame) id))


;; -- Deprecation Messages
Expand Down
112 changes: 112 additions & 0 deletions src/re_frame/frame.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
(ns re-frame.frame
(:require
[re-frame.events :as events]
[re-frame.subs :as subs]
[re-frame.events :as events]
[re-frame.fx :as fx]
[re-frame.cofx :as cofx]
[re-frame.router :as router]
[re-frame.registry :as reg]
[re-frame.std-interceptors :as stdi]))

(defprotocol IFrame
;; dispatch ----
(dispatch [this event-v])
(dispatch-sync [this event-v])

;; subs ----
(reg-sub-raw [this query-id handler-fn])
(reg-sub [this query-id args])
(subscribe
[this query-v]
[this query-v dyn-v])
(clear-sub [this query-id])
(clear-subscriptions-cache [this])

;; fx ----
(reg-fx [this fx-id handler-fn])
(clear-fx [this fx-id])

;; cofx ----
(reg-cofx [this cofx-id handler-fn])
(inject-cofx
[this cofx-id]
[this cofx-id value])
(clear-cofx [this cofx-id])

;; events ----
(clear-event [this event-id])
(reg-event-db
[this id db-handler]
[this id interceptors db-handler])
(reg-event-fx
[this id fx-handler]
[this id interceptors fx-handler])
(reg-event-ctx
[this id handler]
[this id interceptors handler]))

;; connect all the pieces of state ----
(defrecord Frame [registry event-queue app-db subscriptions-cache]
IFrame
;; dispatch ----
(dispatch [this event-v]
(router/dispatch event-queue event-v))
(dispatch-sync [this event-v]
(router/dispatch-sync event-queue registry event-v))

;; subs ----
(reg-sub-raw [this query-id handler-fn]
(reg/register-handler registry subs/kind query-id handler-fn))
(reg-sub [this query-id args]
(apply subs/reg-sub this query-id args))
(subscribe [this query-v]
(subs/subscribe this query-v))
(subscribe [this query-v dyn-v]
(subs/subscribe this query-v dyn-v))
(clear-sub [this query-id]
(reg/clear-handlers registry subs/kind query-id))
(clear-subscriptions-cache [this]
(subs/clear-subscription-cache!))

;; fx ----
(reg-fx [this fx-id handler-fn]
(reg/register-handler registry fx/kind fx-id handler-fn))
(clear-fx [this fx-id]
(reg/clear-handlers registry fx/kind fx-id))

;; cofx ----
(reg-cofx [this cofx-id handler-fn]
(reg/register-handler registry cofx/kind cofx-id handler-fn))
(inject-cofx [this cofx-id]
(cofx/inject-cofx registry cofx-id))
(inject-cofx [this cofx-id value]
(cofx/inject-cofx registry cofx-id value))
(clear-cofx [this cofx-id]
(reg/clear-handlers registry cofx/kind cofx-id))

;; events ----
(clear-event [this id]
(reg/clear-handlers registry events/kind id))

(reg-event-db [this id db-handler]
(reg-event-db this id nil db-handler))
(reg-event-db [this id interceptors db-handler]
(events/register
registry
id
[(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/db-handler->interceptor db-handler)]))
(reg-event-fx [this id fx-handler]
(reg-event-fx this id nil fx-handler))
(reg-event-fx [this id interceptors fx-handler]
(events/register
registry
id
[(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/fx-handler->interceptor fx-handler)]))
(reg-event-ctx [this id handler]
(reg-event-ctx this id nil handler))
(reg-event-ctx [this id interceptors handler]
(events/register
registry
id
[(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/ctx-handler->interceptor handler)])))
2 changes: 1 addition & 1 deletion src/re_frame/fx.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
;; -- Builtin Effect Handlers ------------------------------------------------

(defn register-built-in!
[registry event-queue]
[{:keys [registry app-db event-queue] :as frame}]
(let [register (partial reg/register-handler registry kind)]

;; :dispatch-later
Expand Down
14 changes: 7 additions & 7 deletions src/re_frame/subs.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@

(defn subscribe
"Returns a Reagent/reaction which contains a computation"
([registry query-v]
([{:keys [registry app-db]} query-v]
(trace/with-trace {:operation (first-in-vector query-v)
:op-type :sub/create
:tags {:query-v query-v}}
Expand All @@ -86,7 +86,7 @@
(console :error (str "re-frame: no subscription handler registered for: \"" query-id "\". Returning a nil subscription.")))
(cache-and-return query-v [] (handler-fn app-db query-v)))))))

([registry v dynv]
([{:keys [registry app-db]} v dynv]
(trace/with-trace {:operation (first-in-vector v)
:op-type :sub/create
:tags {:query-v v
Expand Down Expand Up @@ -166,7 +166,7 @@
of an `input signals` functions. `:<-` is supplied followed by the subscription
vector.
"
[registry query-id & args]
[{:keys [registry app-db] :as frame} query-id & args]
(let [computation-fn (last args)
input-args (butlast args) ;; may be empty, or one fn, or pairs of :<- / vector
err-header (str "re-frame: reg-sub for " query-id ", ")
Expand All @@ -184,17 +184,17 @@

;; one sugar pair
2 (fn inp-fn
([_] (subscribe registry (second input-args)))
([_ _] (subscribe registry (second input-args))))
([_] (subscribe frame (second input-args)))
([_ _] (subscribe frame (second input-args))))

;; multiple sugar pairs
(let [pairs (partition 2 input-args)
vecs (map last pairs)]
(when-not (every? vector? vecs)
(console :error err-header "expected pairs of :<- and vectors, got:" pairs))
(fn inp-fn
([_] (map (partial subscribe registry) vecs))
([_ _] (map (partial subscribe registry) vecs)))))]
([_] (map (partial subscribe frame) vecs))
([_ _] (map (partial subscribe frame) vecs)))))]
(reg/register-handler
registry
kind
Expand Down
2 changes: 1 addition & 1 deletion test/re-frame/restore_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

;; TODO: future tests in this area could check DB state and registrations are being correctly restored.

(use-fixtures :each {:before (partial subs/clear-all-handlers! core/registry)})
(use-fixtures :each {:before (partial subs/clear-all-handlers! (:registry core/the-frame))})

(defn one? [x] (= 1 x))
(defn two? [x] (= 2 x))
Expand Down
Loading

0 comments on commit a38ba42

Please sign in to comment.