init commit

This commit is contained in:
Adam Jeniski 2025-07-18 08:04:26 -09:00
commit 8a3f9fee9a
9 changed files with 276 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.nrepl-port
.cpcache

15
README.md Normal file
View 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
View 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]"]}}}

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

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

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