shadow-cljs

https://github.com/thheller/shadow-cljs | https://github.com/sponsors/thheller | https://www.patreon.com/thheller
Iheatu Wogu 2021-03-08T12:30:44.263700Z

Iā€™m trying to run

:test-ci {:target  :node-test
                          :output-to "out/node-test/js"
                          :autorun "true"
                          :js-options {:resolve {"devcards-marked" {:target :npm :require "marked"}
                                                 "devcards-syntax-highlighter" {:target :npm :require "highlight.js"}}}}}
but I get
[:test-ci] Compiling ...
The required namespace "devcards-marked" is not available, it was required by "devcards/util/markdown.cljs".
Iā€™m quite unsure what I might have done wrong

Dan Maltbie 2021-03-08T14:51:43.268800Z

I have two packages, one is the app and the other is a library on which it depends. This library is actually a dual CLJ/CLJS library. For development ease with Clojure using leiningen, I can set a soft link to the library package directory from the app package directory (in the checkouts subdirectory of the app package directory). Is there a way to do something like this for development purposes with shadow-cljs where the app is a CLJS program? Or other ways to simplify development with local package dependencies?

Dan Maltbie 2021-03-09T18:07:28.291500Z

It's like peeling the layers of an onion... Thanks for the pointer. Looks like something that should help.

Dan Maltbie 2021-03-09T18:09:49.291800Z

shadow-cljs is awesome!

flowthing 2021-03-08T19:26:14.269700Z

The simplest way that I know of to get a JVM ClojureScript REPL that I can connect my editor to (basically, just a REPL without a prompt) is to start a Clojure socket REPL (e.g. via the system property) and do something like this:

((requiring-resolve 'cljs.repl/repl)
  ((requiring-resolve 'cljs.repl.browser/repl-env))
  :need-prompt (constantly false)
  :prompt (constantly ""))
But what if I have shadow-cljs in the mix? Does shadow-cljs expose a repl-env that I can pass to cljs.repl/repl? The most straightforward method I know of is to start a Clojure socket REPL and call (shadow.api/repl :id), but there doesn't seem to be a way to disable the prompt. Also, promoting a Clojure REPL to a ClojureScript REPL is rather problematic as far as editor integrations go, because it's difficult for the editor to know whether it's in Clojure or ClojureScript mode. I'd rather have a whole separate socket connection for the ClojureScript REPL, but I haven't found a way to do that with shadow-cljs.

thheller 2021-03-08T19:29:45.271400Z

@flowthing there is no cljs.repl/repl equivalent in shadow-cljs but I could add the :prompt config options. why do you not want a prompt? what editor did you use? most editors use nrepl and not many people use the socket repl at all

flowthing 2021-03-08T19:33:02.271500Z

I use Sublime Text, I'm working on my own thing. I don't really want to use nREPL because: a) I don't actually need any of the features it offers b) I'd like to avoid the dependency if I can (and with Clojure, it's relatively easy to upgrade a Socket REPL to implement editor integration) c) it has the same problem regarding switching REPL modes

thheller 2021-03-08T19:33:41.271700Z

c) is fairly straightforward to handle over nrepl though

thheller 2021-03-08T19:33:51.271900Z

i can understand a+b. not a fan of nrepl myself.

thheller 2021-03-08T19:34:22.272100Z

you could use prepl but that is somewhat ugly as well

flowthing 2021-03-08T19:34:37.272300Z

prepl only has structured output, not structured input.

thheller 2021-03-08T19:34:53.272500Z

:prepl {12345 :build-id} will start a prepl on port 12345 for the build-id

thheller 2021-03-08T19:35:10.272700Z

the input is identical to socket repl and prepl? just clojure forms?

flowthing 2021-03-08T19:35:27.272900Z

Yep.

flowthing 2021-03-08T19:36:33.273100Z

Or, well. This is a rather involved topic. šŸ˜› Anyway, a :prompt option would be great, but I'm not yet sure whether I'd actually end up using it. What I'd really like is a way to run a ClojureScript REPL in a way that's agnostic to build tooling.

thheller 2021-03-08T19:37:38.273500Z

given how vastly different the CLJS REPL is from CLJ thats difficult

thheller 2021-03-08T19:37:58.273700Z

and the REPL impl in shadow-cljs is also very very different and supports many features that the default REPLs don't

thheller 2021-03-08T19:38:28.273900Z

the shadow.remote stuff I built might be of interest for you but thats heavily under documented and not final yet

flowthing 2021-03-08T19:38:38.274100Z

Indeed. I do realize it might be a pipe dream, but I think I'm still going to give it a go.

thheller 2021-03-08T19:39:08.274300Z

I tried fixing all the REPL issues I could think of with shadow.remote and one day I'll document and publish it

thheller 2021-03-08T19:39:24.274500Z

but so far its only used internally for everything shadow-cljs and the REPLs do

flowthing 2021-03-08T19:41:54.274700Z

Sounds interesting. I'd like my thing to work with just out-of-the-box ClojureScript, though.

flowthing 2021-03-08T19:42:36.274900Z

If I start a Clojure socket REPL and send this:

((requiring-resolve 'cljs.repl/repl)
             ((requiring-resolve 'cljs.repl.browser/repl-env))
             :need-prompt (constantly false)
             :prompt (constantly ""))
In a shadow-cljs project, I get this:
Execution error (IllegalArgumentException) at shadow.build.cljs-hacks/eval24027$fn (cljs_hacks.cljc:981).

thheller 2021-03-08T19:44:36.275100Z

as I said .. cljs.repl/repl will never work with shadow-cljs

flowthing 2021-03-08T19:45:02.275300Z

Well, you said there's no equivalent. šŸ™‚ But okay, that's good to know.

flowthing 2021-03-08T19:46:02.275500Z

I'll see where I end up with this thing, but I can make an issue about the :prompt thing if it comes to that. In any case, thanks for the help!

thheller 2021-03-08T19:46:15.275700Z

yeah the REPL implementations are so drastically different that I can't provide a compatible repl-env stuff

thheller 2021-03-08T19:46:27.275900Z

what is the issue with :prompt?

flowthing 2021-03-08T19:46:29.276100Z

All right, that's very good to know.

thheller 2021-03-08T19:46:43.276300Z

I mean why is the prompt a problem?

flowthing 2021-03-08T19:46:55.276500Z

I just meant an option to disable the prompt when calling (shadow/api :app).

thheller 2021-03-08T19:47:34.276700Z

yes, but why?

flowthing 2021-03-08T19:47:38.276900Z

When I send forms to be evaluated from my editor, I don't want the prompt to show up in the evaluation results.

thheller 2021-03-08T19:57:07.277100Z

2.11.22 has (shadow/repl :id {:prompt false})

flowthing 2021-03-08T19:57:21.277300Z

Wow, thank you! šŸ™‡:skin-tone-2:

flowthing 2021-03-08T20:08:06.277500Z

Just to demonstrate what I meant: https://tutkain.flowthing.me/before.png https://tutkain.flowthing.me/after.png The first line with => is the "prompt" (really, the namespace indicator) my client prints (disregard the namespace there, it's WIP), the second line is the prompt shadow-cljs printed. The point is just that I'd like to be sure that what I'm getting from the server is just EDN and I can control when foo=> gets printed and how.

flowthing 2021-03-08T20:09:34.277900Z

(Well, in this case it's not just EDN because it can also be whatever stdout gets, but anyway.)

flowthing 2021-03-08T20:09:54.278100Z

I'll stop taking up more of your time -- thanks again!

thheller 2021-03-08T20:48:07.278300Z

well the easy answer is "just use lein" if you have that setup anyways

thheller 2021-03-08T20:48:27.278500Z

shadow-cljs.edn itself doesn't support checkouts or so. you could just add :source-paths to the proper places

Dan Maltbie 2021-03-08T21:11:21.278700Z

Sorry for confusion, I use lein for JVM code and Shadow-cljs for JS. I'll check out :source-paths and see if that can work for me. thanks!!

thheller 2021-03-08T21:13:47.279100Z

just let lein manage the classpath I meant. CLJS related things will still be handled by shadow-cljs

az 2021-03-08T21:25:53.281600Z

Hi all, Iā€™m a little confused on how to best setup a new re-frame project with shadow. I used the re-frame template lein new re-frame <app-name> I see other projects set up differently and Iā€™m wondering what is the consensus on setting this up, if any? Lastly, any reading material you could point out regarding deployment best practices.