Skip to content

Commit

Permalink
Clojure SDK (#540)
Browse files Browse the repository at this point in the history
* Feature: added clojure sdk

Chore: rebasing on latest
(last commit from clojure-sdk d625982)

* Fix: alphabetical order

* Docs: Actual broadcast example

* Test: adding shell test support

Fix: order of options in data-lines for execute scripts events

Fix: fixed signal handling / missing options

Refactor: using the generated constants for boolean options

* Test: passing shell tests

Chore: task build
  • Loading branch information
JeremS authored Jan 29, 2025
1 parent f333707 commit 1e55dcf
Show file tree
Hide file tree
Showing 83 changed files with 4,995 additions and 18 deletions.
79 changes: 79 additions & 0 deletions build/consts_clojure.qtpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{%- func clojureConsts(data *ConstTemplateData) -%}
;; {%s data.DoNotEdit %}
(ns starfederation.datastar.clojure.consts
(:require
[clojure.string :as string]))


(def datastar-key "{%s data.DatastarKey %}")
(def version "{%s data.Version %}")
(def version-client-byte-size {%d data.VersionClientByteSize %})
(def version-client-byte-size-gzip {%d data.VersionClientByteSizeGzip %})


;; -----------------------------------------------------------------------------
;; Default durations
;; -----------------------------------------------------------------------------
{%- for _, d := range data.DefaultDurations -%}
(def default-{%s d.Name.Kebab %}
"{%s= d.Description %}"
{%d durationToMs(d.Duration) %})

{%- endfor -%}

;; -----------------------------------------------------------------------------
;; Default values
;; -----------------------------------------------------------------------------
{%- for _, s := range data.DefaultStrings -%}
(def default-{%s s.Name.Kebab %}
"{%s= s.Description %}"
(-> "{%s s.Value %}"
(string/split #" ")
(update 0 keyword)
(->> (apply array-map))))

{%- endfor -%}

;; -----------------------------------------------------------------------------
;; Dataline literals
;; -----------------------------------------------------------------------------
{%- for _, literal := range data.DatalineLiterals -%}
(def {%s literal.Kebab %}-dataline-literal "{%s literal.Camel %} ")
{%- endfor -%}


;; -----------------------------------------------------------------------------
;; Default booleans
;; -----------------------------------------------------------------------------
{%- for _, b := range data.DefaultBools -%}
(def default-{%s b.Name.Kebab %}
"{%s= b.Description %}"
{%v b.Value %})

{%- endfor -%}


;; -----------------------------------------------------------------------------
;; Enums
;; -----------------------------------------------------------------------------
{%- for _, enum := range data.Enums -%}
;; {%s enum.Name.Pascal %}

{%- for _, entry := range enum.Values -%}
(def {%s enum.Name.Kebab %}-{%s entry.Name.Kebab %}
"{%s= entry.Description %}"
"{%s entry.Value %}")

{%- endfor -%}

{%- if enum.Default != nil -%}
(def default-{%s enum.Name.Kebab %}
"Default value for {%s enum.Name.Pascal %}.
{%s= enum.Default.Description %}"
{%s enum.Name.Kebab %}-{%s enum.Default.Name.Kebab %})
{%- endif -%}


{%- endfor -%}

{%- endfunc -%}
38 changes: 20 additions & 18 deletions build/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,27 +131,29 @@ func writeOutConsts(version string) error {
})

templates := map[string]func(data *ConstTemplateData) string{
"README.md": datastarREADME,
"library/README.md": datastarREADME,
"library/src/engine/consts.ts": datastarClientConsts,
"library/package.json": datastarClientPackageJSON,
"sdk/go/consts.go": goConsts,
"sdk/dotnet/src/Consts.fs": dotnetConsts,
"sdk/php/src/Consts.php": phpConsts,
"sdk/php/src/enums/EventType.php": phpEventType,
"sdk/php/src/enums/FragmentMergeMode.php": phpFragmentMergeMode,
"README.md": datastarREADME,
"library/README.md": datastarREADME,
"library/src/engine/consts.ts": datastarClientConsts,
"library/package.json": datastarClientPackageJSON,
"sdk/clojure/sdk/src/main/starfederation/datastar/clojure/consts.clj": clojureConsts,
"sdk/go/consts.go": goConsts,
"sdk/dotnet/src/Consts.fs": dotnetConsts,
"sdk/php/src/Consts.php": phpConsts,
"sdk/php/src/enums/EventType.php": phpEventType,
"sdk/php/src/enums/FragmentMergeMode.php": phpFragmentMergeMode,
"sdk/java/core/src/main/java/starfederation/datastar/Consts.java": javaConsts,
"sdk/java/core/src/main/java/starfederation/datastar/enums/EventType.java": javaEventType,
"sdk/java/core/src/main/java/starfederation/datastar/enums/FragmentMergeMode.java": javaFragmentMergeMode,
"sdk/python/src/datastar_py/consts.py": pythonConsts,
"sdk/typescript/src/consts.ts": typescriptConsts,
"sdk/rust/src/consts.rs": rustConsts,
"sdk/zig/src/consts.zig": zigConsts,
"examples/dotnet/HelloWorld/wwwroot/hello-world.html": helloWorldExample,
"examples/go/hello-world/hello-world.html": helloWorldExample,
"examples/php/hello-world/public/hello-world.html": helloWorldExamplePHP,
"examples/zig/httpz/hello-world/src/hello-world.html": helloWorldExample,
"examples/zig/tokamak/hello-world/hello-world.html": helloWorldExample,
"sdk/python/src/datastar_py/consts.py": pythonConsts,
"sdk/typescript/src/consts.ts": typescriptConsts,
"sdk/rust/src/consts.rs": rustConsts,
"sdk/zig/src/consts.zig": zigConsts,
"examples/clojure/hello-world/resources/public/hello-world.html": helloWorldExample,
"examples/dotnet/HelloWorld/wwwroot/hello-world.html": helloWorldExample,
"examples/go/hello-world/hello-world.html": helloWorldExample,
"examples/php/hello-world/public/hello-world.html": helloWorldExamplePHP,
"examples/zig/httpz/hello-world/src/hello-world.html": helloWorldExample,
"examples/zig/tokamak/hello-world/hello-world.html": helloWorldExample,
}

for path, tmplFn := range templates {
Expand Down
2 changes: 2 additions & 0 deletions examples/clojure/hello-world/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.nrepl-port
.cpcache
15 changes: 15 additions & 0 deletions examples/clojure/hello-world/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Hello world example

## Running the example

- repl:

```
clojure -M:repl -m nrepl.cmdline --middleware "[cider.nrepl/cider-middleware]"
```

- main:

```
clojure -M -m example.main
```
15 changes: 15 additions & 0 deletions examples/clojure/hello-world/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{:paths ["src/main" "resources"]

:deps {
starfederation.datastar/sdk {:local/root "../../../sdk/clojure/sdk"}
starfederation.datastar/ring-jetty {:local/root "../../../sdk/clojure/adapter-jetty"}
metosin/reitit {:mvn/version "0.7.2"}
dev.onionpancakes/chassis {:mvn/version "1.0.365"}
com.cnuernber/charred {:mvn/version "1.034"}}

:aliases
{:repl {:extra-paths ["src/dev"]
:extra-deps {org.clojure/clojure {:mvn/version "1.12.0"}
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"}}}}}
35 changes: 35 additions & 0 deletions examples/clojure/hello-world/resources/public/hello-world.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!-- This is auto-generated by Datastar. DO NOT EDIT. -->

<!DOCTYPE html>
<html lang="en">
<head>
<title>Datastar SDK Demo</title>
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.2/bundles/datastar.js"></script>
</head>
<body class="bg-white dark:bg-gray-900 text-lg max-w-xl mx-auto my-16">
<div data-signals-delay="400" class="bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 rounded-lg px-6 py-8 ring shadow-xl ring-gray-900/5 space-y-2">
<div class="flex justify-between items-center">
<h1 class="text-gray-900 dark:text-white text-3xl font-semibold">
Datastar SDK Demo
</h1>
<img src="https://data-star.dev/static/images/rocket.png" alt="Rocket" width="64" height="64"/>
</div>
<p class="mt-2">
SSE events will be streamed from the backend to the frontend.
</p>
<div class="space-x-2">
<label for="delay">
Delay in milliseconds
</label>
<input data-bind-delay id="delay" type="number" step="100" min="0" class="w-36 rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-sky-500 focus:outline focus:outline-sky-500 dark:disabled:border-gray-700 dark:disabled:bg-gray-800/20" />
</div>
<button data-on-click="@get(&#39;/hello-world&#39;)" class="rounded-md bg-sky-500 px-5 py-2.5 leading-5 font-semibold text-white hover:bg-sky-700 hover:text-gray-100 cursor-pointer">
Start
</button>
</div>
<div class="my-16 text-8xl font-bold text-transparent" style="background: linear-gradient(to right in oklch, red, orange, yellow, green, blue, blue, violet); background-clip: text">
<div id="message">Hello, world!</div>
</div>
</body>
</html>
21 changes: 21 additions & 0 deletions examples/clojure/hello-world/src/dev/user.clj
Original file line number Diff line number Diff line change
@@ -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)


61 changes: 61 additions & 0 deletions examples/clojure/hello-world/src/main/example/core.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
(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-jetty :refer [->sse-response]]))


(def home-page
(-> (io/resource "public/hello-world.html")
slurp
(string/split-lines)
(->> (drop 3)
(apply str))))


(defn home [_]
(-> home-page
(ruresp/response)
(ruresp/content-type "text/html")))


(def message "Hello, world!")

(def msg-count (count message))


(defn ->frag [i]
(h/html
(hc/compile
[:div {:id "message"}
(subs message 0 (inc i))])))



(defn hello-world [request]
(let [d (-> request u/get-signals (get "delay") int)]
(->sse-response request
{:on-open
(fn [sse]
(d*/with-open-sse sse
(dotimes [i msg-count]
(d*/merge-fragment! sse (->frag i))
(Thread/sleep d))))})))


(def routes
[["/" {:handler home}]
["/hello-world" {:handler hello-world
:middleware [rmparams/parameters-middleware]}]])

(def router (rr/router routes))

(def handler (rr/ring-handler router))

8 changes: 8 additions & 0 deletions examples/clojure/hello-world/src/main/example/main.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(ns example.main
(:require
[example.core :as c]
[example.server :as server]))


(defn -main [& _]
(server/start! c/handler {:join? true}))
32 changes: 32 additions & 0 deletions examples/clojure/hello-world/src/main/example/server.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
(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}]
(jetty/run-jetty handler
(merge {:port 8080 :join? false}
opts)))


(defn stop! [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))
13 changes: 13 additions & 0 deletions examples/clojure/hello-world/src/main/example/utils.clj
Original file line number Diff line number Diff line change
@@ -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))


6 changes: 6 additions & 0 deletions sdk/clojure/.clj-kondo/config.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{:lint-as {fr.jeremyschoffen.datastar.utils/defroutes clojure.core/def
starfederation.datastar.clojure.utils/transient-> clojure.core/->}
:hooks
{:analyze-call
{test.utils/with-server hooks.test-hooks/with-server}}}

17 changes: 17 additions & 0 deletions sdk/clojure/.clj-kondo/hooks/test_hooks.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
(ns hooks.test-hooks
(:require
[clj-kondo.hooks-api :as api]))


(defn with-server [{:keys [node] :as exp}]
(let [[s-name handler opts & body] (-> node :children rest)
underscore (api/token-node '_)
new-children (list*
(api/token-node 'let)
(api/vector-node
[s-name handler
underscore opts])
body)
new-node (assoc node :children new-children)]
(assoc exp :node new-node)))

11 changes: 11 additions & 0 deletions sdk/clojure/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.cpcache
.nrepl-port
.lsp
.clj-kondo/**
!.clj-kondo/config.edn
!.clj-kondo/hooks**




test-resources/test.config.edn
Loading

0 comments on commit 1e55dcf

Please sign in to comment.