Fork me on GitHub
#shadow-cljs
<
2021-07-12
>
Burin04:07:07

Hi I am trying to build simple node-js library and keep getting the following error when trying to use it in non-dev mode:

Cannot find module 'uuid'\\nRequire stack

my `shadow-cljs.edn` is something like:
{:deps {:aliases [:cljs]} :builds {:handler {:target :node-library :output-to "handler.js" :exports-var example-demo.core/exports :compiler-options {:infer-externs :auto}} :test {:target :node-test :output-to "test.js"} :autotest {:target :node-test :output-to "test.js" And this only happen when I am trying this via
clojure -M:cljs:shadow release handler

My cljs file look like:
(ns example-demo.core (:require ["uuid" :as uuid])) (println "sample uuid: " (uuid/v4)) ;; this work properly when running in in the dev mode via REPL and check the eval the code via editor (defn sample [] ;; ... some code that return js/Promise ) (def exports #js {:sample sample}) I am trying to read through the documentation still I am not sure if someone know if something that I may have missed? Thanks

Karol Wójcik09:07:42

@agilecreativity 😄 I'm seeing what you're trying to do here 😄

Burin13:07:55

Hi @UJ1339K2B yeah you got me, still waiting for holy-lambda to support nodejs 😄

Karol Wójcik13:07:26

Nodejs support will happen in the end of the year most probably. But why not native runtime? It’s significantly faster

Burin13:07:43

At work, we are heavy user of nodejs at the moment from historical reason. Since we use many library that may not work properly with Graalvm natively so that may be some issue to adopt it.

Karol Wójcik13:07:15

Oh I see. That’s sad ;(

Burin13:07:23

I really love the workflow from Clojure though compare to the ClojureScript one.

Karol Wójcik13:07:07

Which libraries hold you in Nodejs if I could ask? Cause maybe it’s possible to interop with those via GraalVM Polyglot API

Burin13:07:01

Like we are using things that talks to Redis for example, I have not yet checked if Carmine is compatible with GraalVM for example.

Burin13:07:25

Or things like honey-sql, etc

Burin13:07:51

but just checked it seems Carmine is compatible with GraalVM https://github.com/BrunoBonacci/graalvm-clojure/tree/master/carmine

Karol Wójcik13:07:07

Oh but you're mentioning now the stuff on Clojure side. I mean that in GraalVM native-image you do interop with node.js

Karol Wójcik13:07:21

honeq-sql should work just fine I think

thheller06:07:36

@agilecreativity node builds by defaults do NOT bundle their dependencies. so whereever you run it you'll need the proper node_modules as well

Burin13:07:33

Thanks @thheller will give that a try.

thheller06:07:04

if you want something self-contained you can post-process the release file with https://github.com/vercel/ncc

David Pham07:07:06

Hello :) In the newest version of shadow-cljs, i think it gets confused to which node_modules folder to use dependencies. I am using deps.edn to refer to an local deps, which also contains a node_modules folder and shadow-cljs extract the js deps from the dependencies node_modules folder, which cause the build to fail as it can’t get js files outside the project. Is it a problem on my side?

David Pham07:07:36

The problem is resolved when I remove/rename the node_modules folder.

David Pham07:07:44

In the dependency lib.

thheller07:07:51

only the node_modules of your project are considered. it does not look at node_modules of libraries, unless you specifically configured that via :js-packages-dirs

David Pham07:07:15

Nope, I did not such things 😕

thheller07:07:34

so what you mean by "it gets confused"?

David Pham07:07:14

I got the following mistakes

Build failure:
Failed to inspect file
  /home/david/Documents/transparency/frontend/node_modules/@date-io/date-fns/build/index.js

it was required from
  /home/david/Documents/transparency/frontend/src/cljs/transparency/reporting/user_input.cljs

files outside the project are not allowed: /home/david/Documents/transparency/frontend/node_modules/@date-io/date-fns/build/index.js
{:file #object[java.io.File 0x6910e23c "/home/david/Documents/transparency/frontend/node_modules/@date-io/date-fns/build/index.js"]}
ExceptionInfo: files outside the project are not allowed: /home/david/Documents/transparency/frontend/node_modules/@date-io/date-fns/build/index.js

David Pham07:07:34

While my main project is at /home/david/Documents/whatever/

David Pham07:07:32

Does it make sense?

thheller07:07:29

and how did you require it?

David Pham07:07:04

in the deps.edn file, under the :deps key

David Pham07:07:04

transparency/transparency {:local/root "lib/transparency"}

David Pham07:07:11

(with a simlink)

thheller07:07:28

deps.edn does not manage or affect JS depdencies in any way. so whatever you do there does NOT affect this

thheller07:07:33

I'm asking how you required it in your code, in your cljs ns :require?

David Pham07:07:04

(:require ["@date-io/date-fns" :as date-fns-utils])

thheller07:07:26

do you have any other config that might affect this? :js-options :resolve or so?

David Pham07:07:48

I use deps.cljs under the root of the source?

thheller07:07:56

in shadow-cljs.edn

David Pham07:07:13

of the main project?

thheller07:07:35

is the node_modules (or anything in it) symlinked?

David Pham07:07:40

nope, nothing

David Pham07:07:51

it is a plain npm i --save

David Pham07:07:22

As I said, if I remove the node_modules from the dep library, it works.

thheller07:07:24

/home/david/Documents/transparency/frontend this is your project folder?

David Pham07:07:33

this is the lib folder

David Pham07:07:05

/home/david/Documents/whatever would be the project folder

thheller07:07:19

oh, hang on. I think I know what might be happening

thheller07:07:16

@neo2551 try shadow-cljs 2.15.1, should be ok again

David Pham07:07:11

Thanks a lot! Sorry for disturbing

thheller07:07:50

thanks for the report 🙂

Simon14:07:44

how do i use "https" node.js standard library to make a request to an external API? If there is another library better suited for ClojureScript what would that be?

Simon14:07:01

(defn book_consultation [req, res]
  ;/book_consultation
  (let [query (.. req -query)
        email (.-email query)]
    (.on
     (.get
      https
      ""
      (fn [resp]
        (let [data ""]
          (.on
           resp
           "end"
           (fn [] (.send res (.. (.parse js/JSON data) -results))))))
      "error"
      (fn [err] (.log js/console (str "Error: " (.-message err))))))))

Simon14:07:53

This is the code i have, but it can't infer the target type:

--------------------------------------------------------------------------------
  12 |       ""
  13 |       (fn [resp]
  14 |         (let [data ""]
  15 |           (.on
-----------------^--------------------------------------------------------------
 Cannot infer target type in expression (. resp on "end" (fn [] (.send res (.. (.parse js/JSON data) -results))))
--------------------------------------------------------------------------------
  16 |            resp
  17 |            "end"
  18 |            (fn [] (.send res (.. (.parse js/JSON data) -results))))))
  19 |       "error"
--------------------------------------------------------------------------------

Simon14:07:43

could i use the cljs.core.async.macros :refer [go] macro? Or would that not work on node.js?

Justin Chandler14:07:08

I'm not the best resource to be asking, so someone can correct me if I'm wrong, but 1. if it says cannot infer target type when using a . function, I'm pretty sure it means you're missing a ^js in front of the variable in question, in your case it'd be fn [^js resp] and ^js res wherever it's declared and 2. you should be able to use macros in both browser and node.js just fine

Simon14:07:24

Yes this is also what i want to use, since i already use it on the client side. Although i run into this error:

>  /Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/goog/net/xmlhttp.js:177
>      return new XMLHttpRequest();
>      ^
>  ReferenceError: XMLHttpRequest is not defined
>      at goog.net.DefaultXmlHttpFactory.createInstance (/Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/goog/net/xmlhttp.js:177:5)
>      at Object.goog.net.XmlHttp (/Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/goog/net/xmlhttp.js:37:36)
>      at goog.net.XhrIo.createXhr (/Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/goog/net/xhrio.js:682:42)
>      at goog.net.XhrIo.send (/Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/goog/net/xhrio.js:530:20)
>      at Object.cljs_http$core$xhr [as xhr] (/Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/cljs_http/core.cljs:107:5)
>      at cljs_http$core$request (/Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/cljs_http/core.cljs:150:5)
>      at /Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/cljs_http/client.cljs:125:7
>      at /Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/cljs_http/client.cljs:207:7
>      at /Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/cljs_http/client.cljs:223:7
>      at /Users/simonchristensen/Documents/Developer/movenation/calculator/.shadow-cljs/builds/firebase-functions/dev/out/cljs-runtime/cljs_http/client.cljs:104:7
With this code:
(defn book_consultation [req, res]
  ;/book_consultation
  (let [query (.. req -query)
        email (.-email query)]
    (go (let [response (<! (http/get ""
                                     {:with-credentials? false}))
              name (get-in response [:body :results :name :first])])
        (.send res (str "name is: " name)))))

Simon14:07:44

It returns a XMLHttpRequest. Which makes sense, but does someone know how to call it correctly?

Simon14:07:33

yeah it's in node.js

Simon15:07:07

It works! Thank you!

(ns functions.index
  (:require ["firebase-functions" :as fun]
            ["https" :default https]
            [cljs.core.async :refer [<!]] [cljs-http.client :as http]
            [cljs.nodejs :as nodejs]
            ["xhr2" :as xhr2])
  (:require-macros [cljs.core.async.macros :refer [go]]))

(set! js/XMLHttpRequest xhr2)

(defn book_consultation [req, res]
  ;/book_consultation
  (let [query (.. req -query)
        email (.-email query)]
    (go (let [response (<! (http/get ""
                                     {:with-credentials? false}))
              name (get-in response [:body :results 0 :name :first])]
          (.send res (str "name is: " name))))))

Simon15:07:43

yeah I just thought it would be more clear if i declare all the imports in require. I am aware i could write (set! js/XMLHttpRequest (nodejs/require "xhr2"))

Simon15:07:05

yeah but then i would be able to write (set! js/XMLHttpRequest xhr2)

Justin Chandler14:07:56

Also as a side note, I really have to compliment the response time of @thheller and @borkdude, the speed and amount of support you both give is amazing, as are your projects! I've been using babashka and shadowCLJS for a while now and I never knew both of you were so accessible hahaha In any case, thank you for your hard work, it's appreciated!

👍 8
8
👏 8
❤️ 8
2
💯 2
sova-soars-the-sora16:07:47

😄 the clojure community rocks. bowie

12
zendevil.eth19:07:02

I’m running the tests like so: shadow-cljs release test and this is my config file:

{:nrepl {:port 7002}
 :builds
 {:app
  {:target     :browser
   :output-dir "target/cljsbuild/public/js"
   :asset-path "/js"
   :modules    {:app {:entries []}}
   :devtools   {:watch-dir "resources/public"
                :preloads  [re-frisk.preload]}
   :dev        {:closure-defines {"re_frame.trace.trace_enabled_QMARK_" true}}
   :release    {}}
  :test {:target   :node-test
         :test-dir "target/node-tests.js"
         :autorun  true
         }}
 :lein  true}
And I’m getting this error: https://gist.github.com/zendevil/6f29c2ac64d8be067e5e5f525b2f059e How can I fix this?

thheller20:07:59

@ps I'm guessing target/node-tests.js is an actual file? when it should be a directory?

zendevil.eth20:07:00

this is a snippet from the user guide:

{...
 :builds
 {:test
  {:target    :node-test
   :output-to "out/node-tests.js"
   :ns-regexp "-spec$"
   :autorun   true}}}

thheller20:07:14

oh right node-test

thheller20:07:22

so yeah. do you see the difference? you are missing :output-to

thheller20:07:49

:test-dir is from :browser-test only