Fork me on GitHub
#scittle
<
2024-02-03
>
Benjamin11:02:55

making some squint components in a ts/ vite project. Works great. I wanted a repl so I am mounting a scittle nrepl server. I made a usage comment for my team mates. Sharing the whole file here:

Benjamin11:02:12

;; =============================================================================
;;                                   USAGE
;; ==============================================================================


;; Scittle:
;; Imagine a piece of javascript that can evaluate clj(s) in the browser
;;
;; (eval code) ....
;;
;;
;; Scittle nrepl server has 2 parts:
;;                                                  2.
;;      1.                                        browser
;;   +-----------+                              +-----------+
;;   |           |          socket              |           |
;; +-+           |<---------------+------------>|           |
;; | +-----------+                |             +-----------+
;; |  'sci repl'                  |              scittle nrepl
;; |  'nrepl server'              |              written in scittle
;; | - runnable with bb           |
;; | written in clj               |
;; |                              SCITTLE_NREPL_WEBSOCKET_PORT
;; |
;; |                                    - requires scittle to be loaded in the browser to run
;; | cider-clj-jack-in -> 1339
;; | or calva jack in
;; |
;; |             3.
;; +---------+ client
;; |         | calva vscode,
;; |         | "your favorite editor"
;; +---------+


;;
;;
;; 1. You need to run a scittle nrepl server
;; --------------------------------
;; cd repo root
;; cd scittle-nrepl
;; bb dev
;;
;; 2. You need to run scittle nrepl server in your browser
;; ---------------------------------------
;; For this, the below react component will load and mount scittle and scittle nrepl server
;;
;; import { ScittleNrepl } from "~/lib/components/ScittleRepl"
;; // somewhere in jsx:
;; <ScittleNrepl></ScittleNrepl>
;;
;; for each page btw
;; or put in in whatever root or header to have it everywhere, didn't think of that yet.
;;
;; 3. Connect to the running nrepl with your editor
;; i.e. calva jack in -> localhost -> port 1339 (the SCITTLE_NREPL_WEBSOCKET_PORT)
;; You might want to reload, if the scittle nrepl server is connecting it logs out something I think.
;; You get the javascript environment of your browser
;; so everything under js/... should be exactly the same for your squint component and during repl.
;;
;;

(ns ScittleRepl
  (:require
   ["react" :as react]
   ;; ["react-dom" :as react-dom]
   ))

(defn use-effect-once [effect-fn]
  (react/useEffect effect-fn #js []))

(defn use-script [src]
  (use-effect-once
    (fn []
      (let [script (js/document.createElement "script")]
        (set! (.-type script) "application/javascript")
        (set! (.-src script) src)
        (set! (.-async script) false)
        (-> js/document
            (.getElementsByTagName "head")
            (.item 0)
            (.appendChild script))
        (fn []
          ;; Cleanup function, if necessary
          )))))

(defn ScittleComponent []
  (use-effect-once (fn [] (set! js/window.SCITTLE_NREPL_WEBSOCKET_PORT 1340) (constantly nil)))
  (use-script "")
  (use-script "")
  #jsx [:div "scittle nrepl server"])

(defn OnClient
  [{:keys [children]}]
  (let [[isClient setIsClient] (react/useState false)
        _ (react/useEffect (fn [] (setIsClient true)))]
    (when isClient #jsx [:div children])))

(defn ScittleNrepl []
  #jsx
  [OnClient
   [ScittleComponent]])


;; ... sure you could be developing react more directly like this, too

;; (defn mount-app []
;;   (let [container (.querySelector js/document "#app")]
;;     (react-dom/render (ScittleComponent) container)))

;; Assuming that you call (mount-app) to mount the component into a <div id="app"></div> in your HTML.

Benjamin11:02:43

scittle-nrepl is a dir with a bb.edn that we know from the example scittle:

{:deps {io.github.babashka/sci.nrepl
          {:git/sha
             "2f8a9ed2d39a1b09d2b4d34d95494b56468f4a23"}}
 :tasks {-dev {:depends [browser-nrepl]}
         browser-nrepl {:doc "Start browser nREPL"
                        :requires ([sci.nrepl.browser-server
                                    :as bp])
                        :task (bp/start! {})}
         dev {:task (do (run '-dev {:parallel true})
                        (deref (promise)))}}}

Benjamin12:02:57

Errata: calva jack in -> localhost -> port 1339 (that is not the "websocket port". That is the nrepl-port.)

borkdude12:02:00

wait, what -- you using squint but also scittle?

Benjamin12:02:34

scittle just for developing. I don't have a repl otherwise.

Benjamin12:02:46

And the scittle nrepl is really funnily powerful

borkdude12:02:30

but how does squint tie into this? :)

Benjamin12:02:57

We have a typescript project and I can write squint components

Benjamin12:02:22

So I write squint but I'm also connected to the browser and Dev some example data ect

borkdude12:02:44

I think I want to do a similar thing for squint projects as the scittle repl

👍 3
borkdude12:02:55

for browser

👍 2