Fork me on GitHub

I'm trying to figure out how to setup a project where deps.edn is used for dependencies and add nrepl middleware (#portal in this case). Failing so far, with a message nREPL middleware: shadow.cljs.devtools.cli has no namespace. Details in 🧵


My deps.edn looks like so:

{:paths ["src" "test" "env/dev"]
 :deps {binaryage/devtools {:mvn/version "1.0.6"}
        djblue/portal {:mvn/version "0.35.0"}
        org.clojure/clojure {:mvn/version "1.11.1"}
        org.clojure/clojurescript {:mvn/version "1.11.60"}
        reagent/reagent {:mvn/version "1.1.1"}
        thheller/shadow-cljs {:mvn/version "2.20.14"}}
 :aliases {:portal {:extra-deps
                    {djblue/portal     {:mvn/version "0.35.0"}}
                    :main-opts ["-m" "nrepl.cmdline"
And shadow-cljs.edn:
{:deps {:aliases [:portal]}
 {8020 "public"}
 {:app {:target :browser
        :output-dir "public/js/compiled"
        :asset-path "/js/compiled"
        :modules {:main {:init-fn main.core/init}}
        :build-hooks [(portal.shadow.remote/hook)]
        :devtools {:preloads [devtools.preload
  :test {:target :node-test
         :autorun true
         :output-to "target/node-test/tests.js"
         :ns-regexp ".*-test$"
         :build-hooks [(portal.shadow.remote/hook)]
         :devtools {:preloads [devtools.preload
Running this:
$ npx shadow-cljs -d cider/cider-nrepl:0.28.5 watch :app :test
shadow-cljs - config: /Users/pez/Projects/shadow-portal/shadow-cljs.edn
shadow-cljs - starting via "clojure"
nREPL middleware: shadow.cljs.devtools.cli has no namespace
Jack-in process exited. Status: 2


@U0ETXRFEW you cant set :main-opts in an alias used by shadow-cljs


you just start via clj normally


so I guess just clj -A:portal


and in that REPL you start the shadow-cljs embedded server


you just add the portal dependency as normal


and configure the middleware in shadow-cljs.edn


via :nrepl {:middleware [portal.nrepl/wrap-portal]}


top level, not build level


Thanks. I'll poke around some with this. The last option I think I can't use because I'm not connecting to that nREPL server, but to the one started by clojure.


yeah but you need to understand that the alias option with main-opts it starting its own new nrepl server


in addition to the one start by npx shadow-cljs ...


so pick one


you should only need one nrepl server


it doesn't make sense to start multiple, so just use the one provided by shadow-cljs


and add the portal middleware to that one


and that should be all there is to it


There are some constraints here imposed by assumptions that Calva makes. And by how output is routed for the different repls. To start with the latter. If I start the REPK with clojure and then start the shadow watchers and cljs-REPL from that REPL, then stdout is routed to the REPL and gets mixed up with REPL output. I prefer to have this output in the terminal where I start the REPL. This happens if I start shadow-cljs and let it start the REPL using clojure. I don't know why this works differently, just that it does. As for the assumptions. Calva does actually connect to the nREPL server started by shadow-cljs if I choose the shadow-cljs jack-in option. (I don't know why I thought differently.) So, in summary. Moving the portal nrepl middleware config to shadow-cljs.edn made things work exactly as I want them to. With the test runner output in the terminal and all. 🎉 Thanks again! I'll try to encode these learnings in an example project. And I will update the Calva docs. I would have had helped from that this time. 😃


what you described doesn't make sense? you are starting via clojure but then don't use it?


I guess I'm confused 😛


If I manage dependencies using tools-deps, then shadow-cljs starts the REPL using clojure. And also will make it start an nREPL server. I can't use that one with Portal nREPL middleware for reasons you have helped me understand here. But that's fine, since Calva will connect to the nREPL server started by shadow-cljs. Does this make sense?


Here's a template/example project wired to use start and use Portal for taps and evaluation results from both Clojure and ClojureScript REPLs.


the reason the tests taps don't show is because the test runtime doesn't connect to the REPL at all


it just runs tests and exits


if you run the tests from a regular node-repl instead they'd show up

Ertugrul Cetin10:12:45

Hi, I'm getting this error after updating shadow-cljs. Any ideas?

Exception in thread "main" Syntax error compiling at (shadow/build/closure.clj:80:3).
Caused by: java.lang.RuntimeException: Unable to find static field: ECMASCRIPT_NEXT_IN in class$LanguageMode
Here is my setup;
[thheller/shadow-cljs "2.20.14" :exclusions [nrepl commons-codec com.cognitect/transit-clj org.clojure/tools.reader]]
[ "v20221102"]
[org.clojure/clojurescript "1.11.60" :exclusions [org.clojure/tools.reader]]


version conflict on the closure compiler version


although that is the version it should be using the error indicate that this is not the version you are getting

Ertugrul Cetin10:12:36

The interesting part is, it works for my co-workers. I've also deleted .m2/repository/com/google/javascript/closure-compiler-unshaded to avoid conflict


could be that you are getting the file from someplace else on the classpath

Ertugrul Cetin10:12:30

any possible solutions that you could have?


open a plain REPL, then (:require ') and ( "com/google/javascript/jscomp/CompilerOptions.class")


see where that is coming from


should be the closure-compiler jar with the above version


if not figure out where that came from 😛

Ertugrul Cetin10:12:28

Will do thanks 🙂

Ertugrul Cetin10:12:49

This did the trick

👍 1

What can I do to start a JS runtime for a :test build? In ^ that ^ project tests are set to :auto-run and that works great. But I can't reach the build via the REPL.


you can't and you are not supposed to


just use a node repl


the test targets are for automated testing (ie. CI) and you dont want to keep those processing running due to some connected websocket


:auto-run isn't for CI, is it?


If I can I make a node repl autrun the tests for me, that would work for me. I'll see if I can make that happen.


can you bind the run-tests function to a key and run them yourself?


I mean I find running all tests after every change a little frustrating myself but do what you want


So, what I actually want to achieve here is to have taps happening from :auto-run tests to end up in Portal. I don't strictly need a REPL for that, but that would make it easier to examine the environment. So, then my next question is, can I hope to ba able to add a tap to these test runs?


I don't know how portal works so I can't tell you


if it wants to keep the node process running I can't stop it from doing so


that would break autorun though


the tap is in full control over what it does


@U1G869VNV knows this better than me, but as I understand it, Portal listens to a port and then the user registers a tap that submits to this port. When I do that from the browser app the tap reaches portal, but from the :node-test target this doesn't happen, even though it uses the same port. This is where I lose track of it and was thinking a REPL might help me.


I don't believe it uses the REPL or any connection provided by shadow-cljs


so its entirely on portal and its tap


but again .. I would strongly encourage to use a REPL and runs the tests from there


the tests targets are supposed to exit when they are done and not linger arround


The transient node process should still be able to tap via the remote client since it's just making http post requests to the jvm process hosting the portal api


I do that already. I'm very attached to workflow of seeing shadow run my tests in a terminal pane while I work, though.