Fork me on GitHub
Jérémie Salvucci15:06:30

Hi, I've been using clojurescript + shadow-cljs for a while and lately I bumped into a few issues related to macros + clojure dependencies. For my clojure projects, I use integrant to manage system components and this is actually very handy to describe the whole system. When I'm working on a project in dev mode, I load the dev configuration and all details are managed directly. But when I'm working with clojurescript (shadow-cljs + clojure deps), I don't have the same abilities and I'd like to address this. How do you manage your profiles (dev, test, prod) with the current ecosystem? Does something relying on integrant exist? I would like to avoid playing with classpath and same filenames to handle this.


could you be more specific on what specific problem you are trying to solve? I mean you can use integrant in CLJS? but what is the particular issue?

Jérémie Salvucci17:06:40

for instance, I want to describe several system components with specific urls and connection details and I have different configurations depending on the loaded profile (dev, test or prod)

Jérémie Salvucci17:06:12

My main issue was related to the fact that integrant is designed for programs using clojure. I don't think I can use integrant to actually load a configuration at the clojurescript level. If I want to describe a foreign api with a specific url for dev and another for test, I can but I won't be able to access these profiles from clojurescript without going through a macro. I may be wrong here…


well, yes the way you get access to a config file is different but you can just load if via xhr or something


in CLJ this isn't a decision at build time and it shouldn't be in CLJS either


so move it to runtime and either get the config via xhr or out of your html or something


if you are running in node you can also just load it from disk of course


the only difference really is that you cannot dynamically require namespaces

Jérémie Salvucci20:06:45

ok, I thought there was something else behind that would prevent this. But if it's just the way config files are accessed, I can try something. Thank you, I'm going to experiment


if it's an option for you, you can "inline" all 3 configs files in your source files and select the correct one using closure define. It's not really "config" anymore though


fyi if you're looking for integrant-like that works in javascript (ie most likely need async components), is what I use.

Jérémie Salvucci13:06:46

Thanks, I'll take a look at it. Right now, I use macros to select the right profile and inline it for integrant to read it on client side

Drew Verlee18:06:11

This is a light survey question. Do you use Yarn or something similar but more then NPM? If so, why or why not?


Trivial question ... is there a more idiomatic way of converting a string into a ClojureScript boolean?

(let [env-defaults {:DEBUG "true"}]
  ; env vars are always strings
  (.valueOf (js/Boolean. (get env-defaults :DEBUG false))))


Depends on the semantics that you need. Maybe a plain (= value "true") is enough.


yeah, true that could work but I would rather be stricter and use a boolean the way the good lawd intended


({"true" true "false" false} s false) 🔥

😂 1

@raymcdermott there's a new function called parse-boolean if you can use a more recent Clojurescript


nice, and yes I can always be super modern!


after playing with it I notice that parse-boolean blows up if it gets nil or a boolean. So in the above case I have to change the default to "false".


so it feels odd that parse-boolean does not treat nil as false


the inputs must be strings for all the parse-foo fns I think by design


[ it's also very modern to complain a lot 😆 ]


ok, it's certainly better than the original version I had


you also want to be careful w/ Boolean ctor in JS has similar problems to Java


I think in your above case it might be ok, not sure


it accepted the false :man-shrugging::skin-tone-3:


I mean using the ctor will make a thing which is not the primitive boolean and won't compare correctly like Java


I don't know the spec for .valueOf in this case


.valueOf does exactly that ... returns the primitive value - that's how I made it work


cos Boolean per se was indeed not useful


and I guess false is OK cos you just pass that value straight through to JS ie no interop needed


I see from your original example why you seem to care about nil and false cases because of your use of get and get default value


I think just merging w/ a real defaults map first gets rid of the problem though - don't need to care about the cases


I want to read a value from the environment to test whether DEBUG is on or off. I'm not sure how merge will help here. I'm probably missing something obvious.