init commit
This commit is contained in:
commit
8a3f9fee9a
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.nrepl-port
|
||||
.cpcache
|
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Hello world example
|
||||
|
||||
## Running the example
|
||||
|
||||
- repl:
|
||||
|
||||
```
|
||||
clj -A:repl
|
||||
```
|
||||
|
||||
- main:
|
||||
|
||||
```
|
||||
clojure -M -m example.main
|
||||
```
|
22
deps.edn
Normal file
22
deps.edn
Normal file
@ -0,0 +1,22 @@
|
||||
{:paths ["src/main" "resources"]
|
||||
|
||||
:deps {
|
||||
starfederation.datastar/sdk {:git/url "https://github.com/starfederation/datastar/"
|
||||
:git/sha "376c4e2411706b942ea0ab937e4c6218d24fb30f"
|
||||
:deps/root "sdk/clojure/sdk"}
|
||||
starfederation.datastar/ring {:git/url "https://github.com/starfederation/datastar/"
|
||||
:git/sha "376c4e2411706b942ea0ab937e4c6218d24fb30f"
|
||||
:deps/root "sdk/clojure/adapter-ring"}
|
||||
ring/ring-jetty-adapter {:mvn/version "1.13.0"}
|
||||
metosin/reitit {:mvn/version "0.7.2"}
|
||||
dev.onionpancakes/chassis {:mvn/version "1.0.365"}
|
||||
com.cnuernber/charred {:mvn/version "1.034"}
|
||||
org.clojure/data.json {:mvn/version "2.5.1"}}
|
||||
|
||||
:aliases
|
||||
{:repl {:extra-paths ["src/dev"]
|
||||
:extra-deps {org.clojure/clojure {:mvn/version "1.12.1"}
|
||||
nrepl/nrepl {:mvn/version "1.3.0"}
|
||||
cider/cider-nrepl {:mvn/version "0.50.2"}
|
||||
io.github.tonsky/clj-reload {:mvn/version "0.7.1"}}
|
||||
:main-opts ["-m" "nrepl.cmdline" "--middleware" "[cider.nrepl/cider-middleware]"]}}}
|
14
resources/public/index.html
Normal file
14
resources/public/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!-- This is auto-generated by Datastar. DO NOT EDIT. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>hello world d*</title>
|
||||
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>
|
||||
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@main/bundles/datastar.js"></script>
|
||||
<!-- put css here -->
|
||||
</head>
|
||||
<body style="outline: solid; 1px; red">
|
||||
%%content%%
|
||||
</body>
|
||||
</html>
|
21
src/dev/user.clj
Normal file
21
src/dev/user.clj
Normal file
@ -0,0 +1,21 @@
|
||||
(ns user
|
||||
(:require
|
||||
[clj-reload.core :as reload]))
|
||||
|
||||
|
||||
(alter-var-root #'*warn-on-reflection* (constantly true))
|
||||
|
||||
|
||||
(reload/init
|
||||
{:no-reload ['user]})
|
||||
|
||||
|
||||
(defn reload! []
|
||||
(reload/reload))
|
||||
|
||||
|
||||
(comment
|
||||
(reload!)
|
||||
*e)
|
||||
|
||||
|
144
src/main/example/core.clj
Normal file
144
src/main/example/core.clj
Normal file
@ -0,0 +1,144 @@
|
||||
(ns example.core
|
||||
(:require
|
||||
[clojure.java.io :as io]
|
||||
[clojure.string :as string]
|
||||
[dev.onionpancakes.chassis.compiler :as hc]
|
||||
[dev.onionpancakes.chassis.core :as h]
|
||||
[example.utils :as u]
|
||||
[reitit.ring.middleware.parameters :as rmparams]
|
||||
[reitit.ring :as rr]
|
||||
[ring.util.response :as ruresp]
|
||||
[starfederation.datastar.clojure.api :as d*]
|
||||
[starfederation.datastar.clojure.adapter.ring :refer [->sse-response on-open on-close] :as dr]
|
||||
[clojure.data.json :as json]))
|
||||
|
||||
(declare conns) ;; for broadcasts
|
||||
|
||||
;; html utils
|
||||
(defn html->str [hiccup-forms]
|
||||
(h/html
|
||||
(hc/compile
|
||||
hiccup-forms)))
|
||||
|
||||
(defn page-template [content]
|
||||
(-> (io/resource "public/index.html")
|
||||
slurp
|
||||
(string/split-lines)
|
||||
(->> (drop 3)
|
||||
(apply str))
|
||||
(string/replace "%%content%%" content)))
|
||||
|
||||
|
||||
;; home page
|
||||
(def home-frag
|
||||
(html->str
|
||||
[:main {:id "main"
|
||||
:data-on-load "@get('/connect')"}
|
||||
[:input {:data-bind "msg"}]
|
||||
[:div {:data-text "$msg"}]
|
||||
[:button {:data-on-click "@get('/hello-world')"} "click for text animation"]]))
|
||||
|
||||
(def home-page
|
||||
(page-template home-frag))
|
||||
|
||||
(defn home [request respond _]
|
||||
(respond
|
||||
(-> home-page
|
||||
ruresp/response
|
||||
(ruresp/content-type "text/html"))))
|
||||
|
||||
|
||||
;; d* api utils
|
||||
(defn patch-signals-edn! [sse edn]
|
||||
(d*/patch-signals! sse (json/write-str edn)))
|
||||
|
||||
(defn add-elements! [sse elems]
|
||||
(d*/patch-elements! sse elems #:d*.elements{:patch-mode "append"
|
||||
:selector "body"}))
|
||||
(defn try!
|
||||
[d*-f! sse & args]
|
||||
(try (apply d*-f! sse args)
|
||||
(catch Exception _
|
||||
(println "exception occured. dropping connection")
|
||||
(d*/close-sse! sse)
|
||||
(swap! conns disj sse))))
|
||||
|
||||
|
||||
;; broadcast utils
|
||||
(def conns (atom #{}))
|
||||
|
||||
(defn broadcast!
|
||||
([f]
|
||||
(doseq [conn @conns]
|
||||
(try! f conn)))
|
||||
([f arg & args]
|
||||
(doseq [conn @conns]
|
||||
(apply try! f conn arg args))))
|
||||
|
||||
(defn broadcast-signals! [data]
|
||||
(broadcast! patch-signals-edn! data))
|
||||
|
||||
(defn broadcast-js! [js-src]
|
||||
(broadcast! add-elements! (html->str [:script js-src])))
|
||||
|
||||
(defn broadcast-reload! []
|
||||
(broadcast-js! "location.reload()"))
|
||||
|
||||
(defn kill-broadcast! []
|
||||
(doseq [conn @conns]
|
||||
(try! d*/close-sse! conn)
|
||||
(swap! conns disj conn)))
|
||||
|
||||
(defn connect [request respond _raise]
|
||||
(respond
|
||||
(->sse-response request
|
||||
{on-open
|
||||
(fn [sse] (swap! conns conj sse)
|
||||
(println "adding connection"))
|
||||
on-close
|
||||
(fn [sse]
|
||||
(swap! conns disj sse)
|
||||
(println "dropping connection"))})))
|
||||
|
||||
|
||||
;; hello world animation
|
||||
(def message "Hello, world!")
|
||||
|
||||
(def msg-count (count message))
|
||||
|
||||
(defn hello-world [request respond _raise]
|
||||
(respond
|
||||
(->sse-response request
|
||||
{on-open
|
||||
(fn [sse]
|
||||
(d*/with-open-sse sse
|
||||
(dotimes [i msg-count]
|
||||
(patch-signals-edn! sse {:msg (subs message 0 (inc i))})
|
||||
(Thread/sleep 500))))})))
|
||||
|
||||
|
||||
;; http stuffs
|
||||
(def routes
|
||||
[["/" {:handler home}]
|
||||
["/connect" {:handler connect}]
|
||||
["/hello-world" {:handler hello-world}]])
|
||||
|
||||
(def router (rr/router routes))
|
||||
|
||||
(def handler (rr/ring-handler router))
|
||||
|
||||
|
||||
;; repl it up ;P
|
||||
(comment
|
||||
(broadcast-signals! {:msg "hi franz"})
|
||||
(broadcast-signals! {:msg "hi ty"})
|
||||
(broadcast! d*/console-log! "hi franz")
|
||||
(broadcast-js! "console.log('test')")
|
||||
(broadcast-reload!)
|
||||
|
||||
(kill-broadcast!)
|
||||
|
||||
|
||||
(clojure.repl/dir d*)
|
||||
(clojure.repl/doc d*/patch-signals!))
|
||||
|
12
src/main/example/main.clj
Normal file
12
src/main/example/main.clj
Normal file
@ -0,0 +1,12 @@
|
||||
(ns example.main
|
||||
(:require
|
||||
[example.core :as c]
|
||||
[example.server :as server]))
|
||||
|
||||
|
||||
(defn -main [& _]
|
||||
(let [server (server/start! c/handler)]
|
||||
(.addShutdownHook (Runtime/getRuntime)
|
||||
(Thread. (fn []
|
||||
(server/stop! server)
|
||||
(shutdown-agents))))))
|
33
src/main/example/server.clj
Normal file
33
src/main/example/server.clj
Normal file
@ -0,0 +1,33 @@
|
||||
(ns example.server
|
||||
(:require
|
||||
[example.core :as c]
|
||||
[ring.adapter.jetty :as jetty])
|
||||
(:import
|
||||
org.eclipse.jetty.server.Server))
|
||||
|
||||
|
||||
(defonce !jetty-server (atom nil))
|
||||
|
||||
|
||||
(defn start! [handler & {:as opts}]
|
||||
(let [opts (merge {:port 80 :join? false}
|
||||
opts)]
|
||||
(println "Starting server on port:" (:port opts))
|
||||
(jetty/run-jetty handler opts)))
|
||||
|
||||
|
||||
(defn stop! [server]
|
||||
(println "Stopping server")
|
||||
(println server)
|
||||
(.stop ^Server server))
|
||||
|
||||
|
||||
(defn reboot-jetty-server! [handler & {:as opts}]
|
||||
(swap! !jetty-server
|
||||
(fn [server]
|
||||
(when server
|
||||
(stop! server))
|
||||
(start! handler opts))))
|
||||
|
||||
(comment
|
||||
(reboot-jetty-server! #'c/handler {:async? true}))
|
13
src/main/example/utils.clj
Normal file
13
src/main/example/utils.clj
Normal file
@ -0,0 +1,13 @@
|
||||
(ns example.utils
|
||||
(:require
|
||||
[charred.api :as charred]
|
||||
[starfederation.datastar.clojure.api :as d*]))
|
||||
|
||||
|
||||
(def ^:private bufSize 1024)
|
||||
(def read-json (charred/parse-json-fn {:async? false :bufsize bufSize}))
|
||||
|
||||
(defn get-signals [req]
|
||||
(-> req d*/get-signals read-json))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user