refactor, using cljx to share common server and client code

This commit is contained in:
Gered 2014-12-24 15:37:45 -05:00
parent 0a1ee1df25
commit 143939af61
4 changed files with 62 additions and 70 deletions

View file

@ -9,5 +9,16 @@
[org.clojure/core.async "0.1.346.0-17112a-alpha"]
[net.thegeez/clj-browserchannel-server "0.1.0"]]
:source-paths ["src/clj"]
:resource-paths ["src/cljs"])
:source-paths ["target/generated/src/clj" "src/clj"]
: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"]])

View file

@ -2,40 +2,14 @@
(:refer-clojure :exclude [send])
(:require [clojure.edn :as edn]
[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 incoming-messages (chan))
(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
"sends a browserchannel message to a client identified by the given
browserchannel session id. topic should be a keyword, while body can be
@ -110,9 +84,7 @@
(this differs from net.thegeez.browserchannel/wrap-browserchannel).
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
(browserchannel/wrap-browserchannel
@ -123,9 +95,6 @@
(fn [browserchannel-session-id request]
(handle-session browserchannel-session-id request))))))
(defn- get-handlers [middleware k]
(->> middleware (map k) (remove nil?) (doall)))
(defn init!
"Sets up browserchannel for server-side use. This function should be called
once during application startup.

View file

@ -4,7 +4,8 @@
[cljs.reader :as reader]
[cljs.core.async :refer [pub sub chan <! put!]]
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))
@ -14,34 +15,6 @@
(defonce incoming-messages-pub (pub incoming-messages :topic))
(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
"sends a browserchannel message to the server asynchronously."
[topic body]
@ -67,12 +40,12 @@
(:on-send @handler-middleware)
(fn [msg]
(if-let [encoded (encode-message msg)]
(.sendMap channel encoded)))
(.sendMap channel (clj->js encoded))))
msg)
(recur))))
(defn- handle-incoming [channel msg]
(when-let [decoded (decode-message msg)]
(when-let [decoded (decode-message (js->clj msg))]
(run-middleware
(:on-receive @handler-middleware)
(fn [msg]
@ -129,9 +102,6 @@
(if-let [logger (-> browser-channel .getChannelDebug .getLogger)]
(.setLevel logger level)))
(defn- get-handlers [middleware k]
(->> middleware (map k) (remove nil?) (doall)))
(defn- register-middleware! [middleware]
(reset!
handler-middleware

View 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)))