Fork me on GitHub
#clojurescript
<
2023-02-04
>
Braden Shepherdson00:02:06

I'm wrestling with how to handle cross-platform macros with dependencies. in particular I want to write log, warn, fatal etc. from clojure.tools.logging in a CLJS-friendly way. on JVM, using clojure.tools.logging itself, and on CLJS using glogi. • I tried just using a CLJC namespace first, but that doesn't work because when the CLJS compiler loads the Clojure side to get the macros, it tries to require clojure.tools.logging, which isn't in the CLJS deps. • I tried splitting the namespace into CLJS and CLJ flavours with the same name; same problem. • I tried putting actual functions, no macros, into an impl.cljc, and depending on it from a log.clj with the macros + log.cljs with :refer-macros. that still breaks, it's the same problem but transitive. • I tried using macrovich's case to hide a real-`:clj`-context-only (require 'clojure.tools.logging), but that doesn't work either, not sure why. it really feels like there's a correct way to do this out there, but I'm pretty stuck. any pointers?

Braden Shepherdson00:02:02

Yes, in a few permutations.

Braden Shepherdson00:02:41

It seems like that's arguing for just requiring c.t.l in both settings. It doesn't reach the compiled JS in any case.

Braden Shepherdson00:02:09

What I really want is more options in the reader conditional. :clj/macro vs. :clj/native

phronmophobic00:02:22

I think there's a way to tell if a clj macro is expanding cljs code, but I forget the magical incantation.

Braden Shepherdson00:02:59

The :ns &env hack, yeah. Macrovich/case uses that

phronmophobic00:02:59

I don't think it's possible to know at readtime, so I think it would require a macro

phronmophobic00:02:47

you would then have to wrap calls to functions to the c.t.l namespace with something like requiring-resolve or a delay

Braden Shepherdson00:02:10

Ooh, a delay might cut it. I'm away from my laptop right now, but that feels like it's worth trying.

Michael23:02:09

ok, figured I'd ask in here since the slack looks a lot more active than the discord... I'm using cljs-http as seen in the attached images, but getting the following error at build time:

[:app] Configuring build.
[:app] Compiling ...
[:app] Build failure:
The required namespace "cljs-http.client" is not available, it was required by "reagent_test/ncbi.cljs".

Sam Ritchie23:02:38

I think the keyword in deps.edn should be :deps

Sam Ritchie23:02:59

(Or are they both allowed?)

Sam Ritchie23:02:34

I’ve always used :paths and :deps

p-himik23:02:10

That looks like a part of a profile in project.clj and not deps.edn. @U04MNATSXJN Are you sure that profile is active at build time?

Michael23:02:43

it's in shadow-cljs.edn

p-himik23:02:02

Ah, then you probably have a shadow-cljs server running somewhere in that project's directory that had been started before you've added the cljs-http dependency. I think that even if you manage your dependencies with shadow-cljs.edn, you still have to restart the server to take their changes into account.

dpsutton23:02:08

I have

{:dependencies [[cljs-http "0.1.46"]]}
in shadow-cljs.edn and then i'm running
❯ npx shadow-cljs browser-repl
shadow-cljs - config: /private/tmp/shadow/shadow-cljs.edn
[2023-02-04 17:34:15.767 - WARNING] TCP Port 9630 in use.
shadow-cljs - server version: 2.20.20 running at 
shadow-cljs - nREPL server started on port 57508
[:browser-repl] Configuring build.
[:browser-repl] Compiling ...
[:browser-repl] Build completed. (121 files, 0 compiled, 0 warnings, 2.16s)
cljs.user=> (require '[cljs-http.client :as http])

cljs.user=> (dir http)
decode-body
delete
escape-special
generate-form-data
generate-query-string
get
...

dpsutton23:02:40

i think the shadow-cljs server still running and not restarted is a great hypothesis

Michael23:02:34

I found a java process containing cljs with htop, killed that

Michael23:02:50

I also ended up having to nuke .shadow-cljs

Michael23:02:01

works now, thanks for the help guys 👍

dpsutton23:02:08

that second part is surprising.

Michael23:02:37

yeah it was giving me a socket connection error:

shadow-cljs - socket connect failed, server process dead?

Michael23:02:59

looked it up and the top stackoverflow post said to just clear whatever's cached in .shadow-cljs

Michael23:02:24

welp that took an embarrassingly long time 🤡

Sam Ritchie23:02:36

Join the club ;) we’ve all been there

❤️ 2
dpsutton23:02:14

how are you starting shadow?

Michael23:02:42

i have yarn dev bound to shadow-cljs watch app

dpsutton23:02:45

ah. that may make it hard to actually kill the shadow server depending on how yarn dev spawns its other process. might be worth having npx shadow-cljs server in a dedicated terminal. Then you can be sure you've killed the server and not have to find the process like this again

dpsutton23:02:35

shadow will start up a server from the first process that needs it and then others will reuse that server. so if you start one in a dedicated terminal, the watch command from yarn dev will use that server and it will be faster each time it doesn't have to restart a server

Michael23:02:34

I see, that's good advice

Michael23:02:52

wonder if there's a way to keep the binding without spawning the server in the background deep_thinking

Michael23:02:34

bc I usually prefer to use yarn scripts and not have to think about how the sausage is made (vite, rollup, tsc, etc)

hifumi12301:02:03

With CIDER you can M-x cider-jack-in-cljs and automagically start and stop shadow-cljs server. This is what I typically do. I only have NPM scripts set up for compiling release builds of the app

p-himik08:02:21

> wonder if there's a way to keep the binding without spawning the server in the background Not sure what "binding" here means, but you can make every command start its own JVM (and, correspondingly, a shadow-cljs server process) by adding the --force-spawn flag. Pretty much all of these things are documented.