Fork me on GitHub
#shadow-cljs
<
2023-05-08
>
kanwei17:05:10

I'm having a hard time getting environment variable injection to work. In my edn file I have

:closure-defines  {foo.bar/PUBLICKEY #shadow/env "PUBLIC_KEY"}
But I can't seem to use it in the foo.bar namespace. If I (declare PUBLICKEY) then the value is nil when I print it, and if I omit (declare PUBLICKEY) it just doesn't compile. I do see the correct value in the CLOSURE_DEFINES section when inspecting, I just can't figure out how to use it in CLJS

Ben Lieberman17:05:41

js/CLOSURE_DEFINES?

thheller19:05:51

@U03QBKTVA0N you never ever touch js/CLOSURE_DEFINES for anything. You use goog-define.

thheller19:05:20

js/CLOSURE_DEFINES is an implementation detail, and touching it will break in release builds

Ben Lieberman19:05:59

Oh, that's good to know, thanks.

hifumi12317:05:51

you need to (goog-define PUBLICKEY) in the foo.bar namespace and invoke a fresh instance of shadow-cljs (i.e. not reconnect to an existing server) if you use environment variables

kanwei23:05:24

I'm getting this error:

208 |
 209 | (goog-define PUBLICKEY nil)
-------^------------------------------------------------------------------------
Encountered error when macroexpanding cljs.core/goog-define.
IllegalArgumentException: no conversion to symbol
	clojure.core/symbol (core.clj:598)
	clojure.core/symbol (core.clj:591)
	shadow.build.cljs-hacks/goog-define/fn--55122 (cljs_hacks.cljc:701)

hifumi12302:05:17

The default value has to be a string, number, or boolean. In this case, I'd default to an empty string

kanwei13:05:18

thanks! that finally worked. It was arity 2 and definitely needed the default value, but I set it to empty string and it works

kennytilton19:05:19

Thx again @thheller for all the help today. I want to get Matrix and Web/MX fully compatible with Shadow. Looking at the https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html , I see I am in the Gotcha #5 CLJC category. I see you strongly recommend splitting everything into CLJ and CLJS, but I would have to do about a dozen splits -- I like macros, and I like small files. So I would like to go with the option

(ns my.util
  #?(:cljs (:require-macros [my.util])))
The good news is, as much as I like macros, I have not used a helper function to worry about. And I gather the only trick required there is to wrap those in a #?(:clj ....). Btw, would this be the fix to the example in Gotcha 5?
#?(:clj (defn macro-helper [k v] ...))
Beyond that kind of thing, it seems the self-require looks simple. The compiler will sort out the defmacro forms and do the right thing. Is that right?

thheller19:05:33

yes, that would keep it out of the CLJS parts

kennytilton20:05:24

Great. So originally the client file integrity.cljc with

(ns tiltontec.cell.integrity
  (:require
    #?(:cljs [tiltontec.util.base
              :refer-macros [wtrx trx prog1]]
       :clj  [tiltontec.util.base
              :refer :all])
    [tiltontec.util.core
     :refer [ensure-vec err pln plnk fifo-add fifo-peek fifo-pop cl-find]]
    [tiltontec.cell.base
     :refer [un-stopped *pulse* c-pulse c-optimized-away? *one-pulse?* *dp-log* *unfinished-business*
             +client-q-handler+ c-stopped
             *within-integrity* *defer-changes* *depender*]]))
... was complaining about un-stopped being missing from tiltontec.cell.base. Interestingly, I had neglected to modify that with a self-require! Anyway, it now has:
(ns tiltontec.cell.base
  #?(:cljs (:require-macros [tiltontec.cell.base]))
  ...etc...
I now get the error
------ ERROR -------------------------------------------------------------------
 File: jar:file:/Users/kennethtilton/.m2/repository/com/tiltontec/matrix/5.0.2-SNAPSHOT/matrix-5.0.2-SNAPSHOT.jar!/tiltontec/cell/base.cljc
failed to require macro-ns "tiltontec.cell.base", it was required by "tiltontec.cell.base"
Error in phase :compile-syntax-check
IllegalStateException: Can't change/establish root binding of: *print-level* with set
	clojure.lang.Var.set (Var.java:226)
	tiltontec.cell.base/eval26075 (base.cljc:267)
	tiltontec.cell.base/eval26075 (base.cljc:267)
...etc...
I tried wrapping the macro to force a macro NS:
#?(:clj (defmacro un-stopped [& body]
  `(when-not @+stop+
     ~@body)))
...but no luck. Perhaps I am misunderstanding the sel require trick. Do I still have to have a base.clj?

kennytilton20:05:58

That seems to be the case. I am on to the next error. But I am still hoping to avoid all that splitting. Just spotted this syntax from a 2015 SO answer

(ns cljc.core
  #?(:cljs (:require-macros [cljc.core :refer [list-macro]])))
Is the explicit :refer necessary?

thheller05:05:36

...etc... in code snippets doesn't help. you are likely looking at the wrong piece of code. the IllegalStateException very likely has nothing to do with what you do in your ns. no, you don't need an extra base.clj.

thheller05:05:58

yes, that refer is necessary.

thheller06:05:42

if thats the code still then this is what is causing that error

thheller06:05:10

clojure doesn't let you set! vars like that, unless it is already used in binding

thheller06:05:31

which it is not outside the REPL, which I guess is bound by leiningen by default. but wouldn't be in an uberjar or something, so the code would fail to load in a regular CLJ application as well.

kennytilton08:05:59

Ah, I did see set! sail by in one stack trace, almost played with that. And your guess as to why it works for me makes a ton of sense. I saw that usage unexplained in a couple of places, got away with it, and moved on. I use circular data structures and a lot of print debugging, but I can knock off a quick print utility that bonds *print-level* dynamically. Can't wait to try this out, along with the explicit refer. Thx!

thheller09:05:51

it is fine to set *print-level* in the REPL, just not in the middle of the namespace during loading

👍 2