refactor, using cljx to share common server and client code
This commit is contained in:
parent
0a1ee1df25
commit
143939af61
15
project.clj
15
project.clj
|
@ -9,5 +9,16 @@
|
||||||
[org.clojure/core.async "0.1.346.0-17112a-alpha"]
|
[org.clojure/core.async "0.1.346.0-17112a-alpha"]
|
||||||
[net.thegeez/clj-browserchannel-server "0.1.0"]]
|
[net.thegeez/clj-browserchannel-server "0.1.0"]]
|
||||||
|
|
||||||
:source-paths ["src/clj"]
|
:source-paths ["target/generated/src/clj" "src/clj"]
|
||||||
:resource-paths ["src/cljs"])
|
:resource-paths ["target/generated/src/cljs" "src/cljs"]
|
||||||
|
|
||||||
|
:profiles {:dev {:plugins [[com.keminglabs/cljx "0.5.0"]]}}
|
||||||
|
|
||||||
|
:cljx {:builds [{:source-paths ["src/cljx"]
|
||||||
|
:output-path "target/generated/src/clj"
|
||||||
|
:rules :clj}
|
||||||
|
{:source-paths ["src/cljx"]
|
||||||
|
:output-path "target/generated/src/cljs"
|
||||||
|
:rules :cljs}]}
|
||||||
|
|
||||||
|
:prep-tasks [["cljx" "once"]])
|
||||||
|
|
|
@ -2,40 +2,14 @@
|
||||||
(:refer-clojure :exclude [send])
|
(:refer-clojure :exclude [send])
|
||||||
(:require [clojure.edn :as edn]
|
(:require [clojure.edn :as edn]
|
||||||
[clojure.core.async :refer [chan pub sub <! put! go-loop]]
|
[clojure.core.async :refer [chan pub sub <! put! go-loop]]
|
||||||
[net.thegeez.browserchannel :as browserchannel]))
|
[net.thegeez.browserchannel :as browserchannel]
|
||||||
|
[clj-browserchannel-messaging.utils :refer [run-middleware get-handlers encode-message decode-message]]))
|
||||||
|
|
||||||
(defonce ^:private handler-middleware (atom nil))
|
(defonce ^:private handler-middleware (atom nil))
|
||||||
|
|
||||||
(defonce incoming-messages (chan))
|
(defonce incoming-messages (chan))
|
||||||
(defonce incoming-messages-pub (pub incoming-messages :topic))
|
(defonce incoming-messages-pub (pub incoming-messages :topic))
|
||||||
|
|
||||||
(defn- run-middleware [middleware final-handler & args]
|
|
||||||
(let [wrap (fn [handler [f & more]]
|
|
||||||
(if f
|
|
||||||
(recur (f handler) more)
|
|
||||||
handler))
|
|
||||||
handler (wrap final-handler middleware)]
|
|
||||||
(apply handler args)))
|
|
||||||
|
|
||||||
(defn encode-message
|
|
||||||
"encodes a message made up of a topic and body into a format that can be sent
|
|
||||||
via browserchannel to a client. topic should be a keyword, while body can be
|
|
||||||
any Clojure data structure. returns nil if the message could not be encoded."
|
|
||||||
[{:keys [topic body] :as msg}]
|
|
||||||
(if-let [topic (if topic (name topic))]
|
|
||||||
{"topic" topic
|
|
||||||
"body" (pr-str body)}))
|
|
||||||
|
|
||||||
(defn decode-message
|
|
||||||
"decodes a message received via browserchannel into a map composed of a
|
|
||||||
topic and body. returns nil if the message could not be decoded."
|
|
||||||
[msg]
|
|
||||||
(let [topic (get msg "topic")
|
|
||||||
body (get msg "body")]
|
|
||||||
(if topic
|
|
||||||
{:topic (keyword topic)
|
|
||||||
:body (edn/read-string body)})))
|
|
||||||
|
|
||||||
(defn send
|
(defn send
|
||||||
"sends a browserchannel message to a client identified by the given
|
"sends a browserchannel message to a client identified by the given
|
||||||
browserchannel session id. topic should be a keyword, while body can be
|
browserchannel session id. topic should be a keyword, while body can be
|
||||||
|
@ -110,9 +84,7 @@
|
||||||
(this differs from net.thegeez.browserchannel/wrap-browserchannel).
|
(this differs from net.thegeez.browserchannel/wrap-browserchannel).
|
||||||
|
|
||||||
In addition, you can pass event handler functions. Note that the return
|
In addition, you can pass event handler functions. Note that the return
|
||||||
value for all of these handlers is not used.
|
value for all of these handlers is not used."
|
||||||
|
|
||||||
"
|
|
||||||
[handler & [opts]]
|
[handler & [opts]]
|
||||||
(-> handler
|
(-> handler
|
||||||
(browserchannel/wrap-browserchannel
|
(browserchannel/wrap-browserchannel
|
||||||
|
@ -123,9 +95,6 @@
|
||||||
(fn [browserchannel-session-id request]
|
(fn [browserchannel-session-id request]
|
||||||
(handle-session browserchannel-session-id request))))))
|
(handle-session browserchannel-session-id request))))))
|
||||||
|
|
||||||
(defn- get-handlers [middleware k]
|
|
||||||
(->> middleware (map k) (remove nil?) (doall)))
|
|
||||||
|
|
||||||
(defn init!
|
(defn init!
|
||||||
"Sets up browserchannel for server-side use. This function should be called
|
"Sets up browserchannel for server-side use. This function should be called
|
||||||
once during application startup.
|
once during application startup.
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
[cljs.reader :as reader]
|
[cljs.reader :as reader]
|
||||||
[cljs.core.async :refer [pub sub chan <! put!]]
|
[cljs.core.async :refer [pub sub chan <! put!]]
|
||||||
goog.net.BrowserChannel
|
goog.net.BrowserChannel
|
||||||
[goog.events :as events]))
|
[goog.events :as events]
|
||||||
|
[clj-browserchannel-messaging.utils :refer [run-middleware get-handlers encode-message decode-message]]))
|
||||||
|
|
||||||
(defonce ^:private handler-middleware (atom nil))
|
(defonce ^:private handler-middleware (atom nil))
|
||||||
|
|
||||||
|
@ -14,34 +15,6 @@
|
||||||
(defonce incoming-messages-pub (pub incoming-messages :topic))
|
(defonce incoming-messages-pub (pub incoming-messages :topic))
|
||||||
(defonce outgoing-messages (chan))
|
(defonce outgoing-messages (chan))
|
||||||
|
|
||||||
(defn- run-middleware [middleware final-handler & args]
|
|
||||||
(let [wrap (fn [handler [f & more]]
|
|
||||||
(if f
|
|
||||||
(recur (f handler) more)
|
|
||||||
handler))
|
|
||||||
handler (wrap final-handler middleware)]
|
|
||||||
(apply handler args)))
|
|
||||||
|
|
||||||
(defn encode-message
|
|
||||||
"encodes a message composed of a topic and body into a format that can be
|
|
||||||
sent via browserchannel. topic should be a keyword while body can be
|
|
||||||
anything. returns nil if the message could not be encoded."
|
|
||||||
[{:keys [topic body] :as msg}]
|
|
||||||
(if-let [topic (name topic)]
|
|
||||||
(clj->js {"topic" topic
|
|
||||||
"body" (pr-str body)})))
|
|
||||||
|
|
||||||
(defn decode-message
|
|
||||||
"decodes a message received via browserchannel into a map composed of a
|
|
||||||
topic and body. returns nil if the message could not be decoded."
|
|
||||||
[msg]
|
|
||||||
(let [msg (js->clj msg)
|
|
||||||
topic (keyword (get msg "topic"))
|
|
||||||
body (get msg "body")]
|
|
||||||
(if topic
|
|
||||||
{:topic topic
|
|
||||||
:body (reader/read-string body)})))
|
|
||||||
|
|
||||||
(defn send
|
(defn send
|
||||||
"sends a browserchannel message to the server asynchronously."
|
"sends a browserchannel message to the server asynchronously."
|
||||||
[topic body]
|
[topic body]
|
||||||
|
@ -67,12 +40,12 @@
|
||||||
(:on-send @handler-middleware)
|
(:on-send @handler-middleware)
|
||||||
(fn [msg]
|
(fn [msg]
|
||||||
(if-let [encoded (encode-message msg)]
|
(if-let [encoded (encode-message msg)]
|
||||||
(.sendMap channel encoded)))
|
(.sendMap channel (clj->js encoded))))
|
||||||
msg)
|
msg)
|
||||||
(recur))))
|
(recur))))
|
||||||
|
|
||||||
(defn- handle-incoming [channel msg]
|
(defn- handle-incoming [channel msg]
|
||||||
(when-let [decoded (decode-message msg)]
|
(when-let [decoded (decode-message (js->clj msg))]
|
||||||
(run-middleware
|
(run-middleware
|
||||||
(:on-receive @handler-middleware)
|
(:on-receive @handler-middleware)
|
||||||
(fn [msg]
|
(fn [msg]
|
||||||
|
@ -129,9 +102,6 @@
|
||||||
(if-let [logger (-> browser-channel .getChannelDebug .getLogger)]
|
(if-let [logger (-> browser-channel .getChannelDebug .getLogger)]
|
||||||
(.setLevel logger level)))
|
(.setLevel logger level)))
|
||||||
|
|
||||||
(defn- get-handlers [middleware k]
|
|
||||||
(->> middleware (map k) (remove nil?) (doall)))
|
|
||||||
|
|
||||||
(defn- register-middleware! [middleware]
|
(defn- register-middleware! [middleware]
|
||||||
(reset!
|
(reset!
|
||||||
handler-middleware
|
handler-middleware
|
||||||
|
|
42
src/cljx/clj_browserchannel_messaging/utils.cljx
Normal file
42
src/cljx/clj_browserchannel_messaging/utils.cljx
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
(ns clj-browserchannel-messaging.utils
|
||||||
|
(:require
|
||||||
|
#+clj [clojure.edn :as edn]
|
||||||
|
#+cljs [cljs.reader :as reader]))
|
||||||
|
|
||||||
|
#+clj
|
||||||
|
(defn decode-edn [s]
|
||||||
|
(edn/read-string s))
|
||||||
|
|
||||||
|
#+cljs
|
||||||
|
(defn decode-edn [s]
|
||||||
|
(reader/read-string s))
|
||||||
|
|
||||||
|
(defn encode-message
|
||||||
|
"encodes a message made up of a topic and body into a format that can be sent
|
||||||
|
via browserchannel. topic should be a keyword, while body can be
|
||||||
|
any Clojure data structure. returns nil if the message could not be encoded."
|
||||||
|
[{:keys [topic body] :as msg}]
|
||||||
|
(if-let [topic (if topic (name topic))]
|
||||||
|
{"topic" topic
|
||||||
|
"body" (pr-str body)}))
|
||||||
|
|
||||||
|
(defn decode-message
|
||||||
|
"decodes a message received via browserchannel into a map composed of a
|
||||||
|
topic and body. returns nil if the message could not be decoded."
|
||||||
|
[msg]
|
||||||
|
(let [topic (get msg "topic")
|
||||||
|
body (get msg "body")]
|
||||||
|
(if topic
|
||||||
|
{:topic (keyword topic)
|
||||||
|
:body (decode-edn body)})))
|
||||||
|
|
||||||
|
(defn run-middleware [middleware final-handler & args]
|
||||||
|
(let [wrap (fn [handler [f & more]]
|
||||||
|
(if f
|
||||||
|
(recur (f handler) more)
|
||||||
|
handler))
|
||||||
|
handler (wrap final-handler middleware)]
|
||||||
|
(apply handler args)))
|
||||||
|
|
||||||
|
(defn get-handlers [middleware k]
|
||||||
|
(->> middleware (map k) (remove nil?) (doall)))
|
Reference in a new issue