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.