Fork me on GitHub
#shadow-cljs
<
2022-08-15
>
winsome19:08:44

I'm using a cljc crytography library that depends on an npm library (sjcl) for the cljs implementation. It specifies this in a src/deps.cljs file as {:npm-deps {"@fluree/sjcl" "1.0.8-3"}}.

winsome19:08:55

When I fire up the shadow-cljs server, it runs running: npm install --save --save-exact @fluree/sjcl@^1.0.8-3, and installs the dependency as I expect. I can see the dependency in my node modules.

winsome19:08:16

However, when I build it warns that sjcl is not defined.

winsome20:08:00

Where does it go? I've got author rights to the cljc crypto library, is there a different way I should package js dependencies?

thheller20:08:14

what is the actual error?

winsome20:08:31

Every usage of sjcl in the crytography library generates a Use of undeclared Var warning.

winsome20:08:45

And all of it fails at runtime because none of those vars are there.

thheller20:08:08

be more specific please. Otherwise I have to guess too much about what you are describing

winsome20:08:06

Let me put together a small reproduction, it may be easier to show.

thheller20:08:33

just the errors might be enough. don't expect me to run anything before seeing those

winsome20:08:56

Alright, here's one, there are 36 total, all in the same form:

Warning :undeclared-var in fluree/crypto/scrypt.cljc at 40:29
Use of undeclared Var fluree.crypto.scrypt/sjcl

  37 |    (encrypt raw salt n r p 32))
  38 |   ([raw salt n r p dk-len]
  39 |    #?(:clj  (SCrypt/scrypt raw salt n r p dk-len)
  40 |       :cljs (let [rawBits  (sjcl.codec.bytes.toBits raw)
  41 |                   saltBits (sjcl.codec.bytes.toBits salt)
  42 |                   length (* 8 dk-len)
  43 |                   res (sjcl.crypt.scrypt. rawBits saltBits n r p length)]
  44 |               (sjcl.codec.bytes.fromBits res)))))

thheller20:08:48

yeah thats just invalid code

winsome20:08:51

In what way? Because it works (or has worked) in the browser before.

thheller20:08:59

it has ["@fluree/sjcl" :as sjcl]

thheller20:08:21

:as sets up a namespace alias so sjcl.codec.bytes.toBits should be sjcl/codec.bytes.toBits

thheller20:08:52

this also isn't a warning from shadow-cljs?

winsome20:08:14

That's my bad then, I've been trying to convert the build process over to shadow-cljs and assumed that this was new. Now I'm confused as to how this worked before

thheller20:08:24

as far as I'm concerned this is invalid code. it might happen to work accidentally due to some legacy stufff

winsome20:08:13

Alright, so the proper way to do it is to use the sjcl namespace. Thanks for the insight

thheller20:08:47

Use of undeclared Var is not related to npm in any way and those would not generate this error

winsome21:08:42

I'm building a browser package and a node package from the same cljs codebase and I have one namespace that depends on node's fs module. When I build my browser package I get a The required JS dependency "fs" is not available error. There's a helpful note: "fs is part of the node-libs-browser polyfill package to provide node-native package support for none-node builds. You should install shadow-cljs in your project to provide that dependency." Which I have done but I still see the error. Is there another way to fix this error? I'd rather just only try to require the fs module in the node build.

thheller05:08:52

you can set :js-options {:resolve {"fs" false}} in the build config. if the lib however actually tries to use anything from fs that will cause an error

👍 1
alex21:08:39

Does shadow-cljs expose a mechanism for attaching additional headers to the HTTP GET requests for lazy-loaded modules? In our case, we host our code-split JS files on a Google Cloud Storage bucket (with Google Cloud CDN + caching). Because the lazy-loaded modules are a CORS request from browser -> GCS, we want to send along some additional headers to manage CORS

thheller05:08:15

common misconception but CORS headers need to be sent by the server. not the client.

alex13:08:10

Yep I configured the server to send back the access-control-allow-origin CORS header The reason I want to configure the client request is that I'm hoping to send a custom header from the client that can be used by the Cloud CDN as part of the cache key. By default, Cloud CDN ignores the origin request header (because theoretically there can be an unbounded number of origins, in which case the cache is very inefficient). As a result, Cloud CDN is caching headers/responses from one subdomain and sending it back to another requesting subdomain, causing CORS issues (since the access-control-allow-origin header doesn't match the requesting origin) One fix is to set access-control-allow-origin: * on the server side, but I also wanted to explore passing a custom header up that cloud CDN can use as part of the cache key

thheller14:08:18

never heard of anyone using headers to control caching since that at least requires sending the request to verify the cache?

thheller14:08:43

there is also no way to set any headers using the default loader mechanism. you can of course just build your own

alex17:08:56

> for caching you generally do this https://shadow-cljs.github.io/docs/UsersGuide.html#_cacheable_output Yep, we've implemented the module hashes > never heard of anyone using headers to control caching since that at least requires sending the request to verify the cache? For API requests, client passing If-Modified-Since header is a common mechanism. The server checks if the resource has been modified since that datetime -- if so, returns 200 with the response; if not, returns a 304 > there is also no way to set any headers using the default loader mechanism. you can of course just build your own Got it, thank you

thheller17:08:41

if you have the module hashes why bother with any other caching? the purpose of the hashes is that the files can be cached indefinitely and never need to be checked. changing any code will end up changing the hash.

thheller17:08:01

by headers I meant custom headers. if-modified-since and stuff is already handled by the browser and you don't set anything for those yourself.

alex22:08:25

I almost always have a running shadow-cljs watch process on a browser build. I load the app in the browser and connect to the nREPL via CIDER. Occasionally when I try to eval code in my source code buffer or REPL buffer, I get an error that "No JS runtime is available". I then reload the browser, thinking that might make the runtime available again; if that doesn't work, I disconnect from the nREPL server, then reconnect. Recently this hasn't been working for me So today I navigated to Shadow's http server at localhost:9630 to see if it knew about the browser runtime. According to the dashboard, it did not (1st screenshot). I then restarted the shadow-cljs watch process, loaded the app up again in the browser, and verified that the browser runtime was available (2nd screenshot) Do you know what might cause the shadow-cljs process to not recognize the browser runtime? Are there any additional debugging steps I should take?

thheller05:08:58

check the browser console logs

alex13:08:00

I'm not running into the issue right at the moment, but when I do, should I be looking for errors in the console logs?

thheller14:08:07

you should always look in the browser console first yes