This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-11-17
Channels
- # announcements (7)
- # architecture (12)
- # babashka (5)
- # bangalore-clj (4)
- # beginners (70)
- # biff (23)
- # calva (21)
- # clojure (130)
- # clojure-bay-area (3)
- # clojure-berlin (1)
- # clojure-brasil (1)
- # clojure-europe (55)
- # clojure-finland (4)
- # clojure-greece (5)
- # clojure-nl (3)
- # clojure-norway (10)
- # clojurescript (52)
- # code-reviews (4)
- # community-development (1)
- # data-science (7)
- # datahike (6)
- # datomic (1)
- # events (1)
- # figwheel-main (7)
- # fulcro (23)
- # helix (2)
- # honeysql (32)
- # malli (18)
- # membrane (6)
- # nbb (22)
- # nyc (1)
- # off-topic (26)
- # pathom (2)
- # polylith (34)
- # quil (13)
- # releases (1)
- # remote-jobs (4)
- # scittle (1)
- # shadow-cljs (52)
- # sql (24)
- # tools-deps (17)
- # vim (11)
- # web-security (15)
- # xtdb (6)
I loaded an npm module that I made myself today (I'm not a javascript programmer) and shadow didn't complain. But when I try to call one of its functions (nb/base64encode "abc")
, from a REPL I get module$node_modules$nata_borrowed$nataBorrowed.base64encode is not a function
I'm really impressed that I got that far on the first shot! It knows where to find the function, but it says it isn't a function. Maybe this is a clojurescript question. How do I call a function? I see lots of example of calling methods.
@peterd how did you write the JS? did you export the function properly? if its just a named function in the JS file that is not enough, it needs to be exported
@thheller: I put the code in a function that does as shown below (The code can be found here https://github.com/pdenno/nata-borrowed/blob/main/src/nataBorrowed.js)
Thanks for the pointer on native encode/decode. There are more functions that I'll need so I'll need to know how to do this anyway.
//Top of the file looks like this
var utils = require('./utils');
var dateTime = require('./datetime');
const nataBorrowed = (() => {
'use strict';
// Then the function definition
// Bottom of file...
return {
base64encode
};
})();
module.exports = nataBorrowed;
Here is a simpler example.
Following https://www.sitepoint.com/understanding-module-exports-exports-node-js/, I created
const getName = () => {
'use strict'; // Linting wanted this line.
return 'Jim';
};
exports.getName = getName;
Then I did npm publish --dry-run
and copied the results and package.json into a directory
that I placed in my program's node_modules directory. It contained:
-rw-rw-r-- 1 pdenno pdenno 2009 Nov 17 11:51 package.json
-rw-rw-r-- 1 pdenno pdenno 1005 Nov 17 11:55 smallExample-es5.js
-rw-rw-r-- 1 pdenno pdenno 829 Nov 17 11:55 smallExample-es5.min.js
-rw-rw-r-- 1 pdenno pdenno 0 Nov 17 11:55 smallExample.js
-rw-rw-r-- 1 pdenno pdenno 527 Nov 17 11:55 smallExample.min.js
I added smallexample 1.0.0 to my program's package.json and fired up shadow.
npx shadow-cljs -d nrepl/nrepl:1.0.0 -d cider/piggieback:0.5.3 -d cider/cider-nrepl:0.28.5 watch kaocha-test
Connecting with cider-connect-cljs, in the REPL:
(se/getName)
Execution error (TypeError) at (<cljs repl>:1).
module$node_modules$smallexample$smallExample.getName is not a function
I suspect that I just don't know how to call the function.
and which shadow-cljs version do you use? if you do all this from the REPL there were some issues a while ago
(ns rad-mapper.builtin
(:require ...
#?(:cljs ["smallexample" :as se])))
Then I'm just calling it with (se/getName)
for example.
I am using shadow-cljs 2.20.5.
It could be something really stupid. This is all pretty new to me.
To your last two questions: 1. My build config is the :kaocha-test target in this https://github.com/pdenno/RADmapper/blob/main/shadow-cljs.edn 2. I thought that npm would be the natural choice for shadow-cljs, and also the code I'm integrating, from a tool called JSONata, is provided as an npm package. (I have tried loading the entire JSONata npm package, but get the same results.)
so I compiled your project and just added a require for ["jsonata" :as ja]
and then added (js/console.log "ja" ja)
and it appears to be all fine? I can't test your other package locally? or is it somewhere in that repo?
Well, I think I did warn you that it might be something stupid!
My build process created the files shown in the message above, which, as shown, included
-rw-rw-r-- 1 pdenno pdenno 0 Nov 17 11:55 smallExample.js
which I did not notice is a file of size of 0 bytes.
For anyone reading this thread, there were a few useful thing I learned in the process:
Most significantly, I didn't realize that, for example, (require '["jsonata" :as ja])
binds ja to the object that you export from the npm module. You can just evaluate ja
in the REPL and see the object. The object bound to the empty npm module smallExample.js is #js {}. That's good to know for debugging. Secondly, you might have to explicitly do the require in the REPL. Just being in a namespace that requires it might not be enough. (Or perhaps I have another bug to chase down.)
Thanks for the help! Sorry for the noise. shadow-cljs is a great tool.
if you just (in-ns 'your.ns)
in the REPL before having loaded it the namespace will indeed be empty and contain no requires
also note that there are base64 related functions available in the closure library. (:require [goog.crypt.base64 :as b64])
then (b64/decodeString ...)
Hi, with shadow-cljs v2.20.11 I still see the recent core.async java.lang.NoSuchFieldError: __thunk__0__
issue commented on in commit https://github.com/thheller/shadow-cljs/commit/b034b24d8d20e538afe31b6a19087f021d0813e2
After quite a bit of fault searching and trial-and-error. I’ve come to the point where a suggestion or two would be nice.
Some details:
• My project is based on the https://luminusweb.com.
• All was good until shadow-cljs started using core.async v1.6.673
• The issue goes away if I downgrade to core.async v1.5.648
• My dependencies list all versions of clojure, clojurescript, clojurescript, closure-compiler-unshaded and core.async that shadow-cljs requires according to clojars and error message. I also tried moving all of them to :managed-dependencies in project.clj, without noticeable effect.
• As a test I started out with a clean lein new luminus myproject +shadow-cljs
and bumped shadow-cljs to v2.20.11 and all mentioned libs to the versions shadow requires, it still worked. I then started adding other libs my project uses and error reappeared when I added [com.wsscode/pathom3 "2022.10.19-alpha"]
as a dependency and required it as [com.wsscode.pathom3.connect.operation :as pco]
in myproject/core.clj
. I noticed that Pathom3 also uses shadow-cljs.
It’s honestly not that clear to me which library is to “blame” here. Seems like a snowballing effects starting with a change to core.async, but this is all a bit deeper than where I usually spend my time.
Staying at core.async v1.5.648 might be a workaround for now, but does not seem like a good option in the long run. Other suggestions would be very much appreciated.
the blame is core.async I guess, not exactly sure why this is all even a problem but AOT is weird that way
is there a way to be less aggressive about compiling this:
(def query (js-template graphql "
query reagentProject_pages_homeQuery {
rates(currency: \"USD\") {
currency
rate
}
}
"))
...
(let [{:keys [rates]} (-> useLazyLoadQuery query)]
such that instead of getting this:
reagent_project.pages.home.query = module$node_modules$react_relay$index.graphql`
query reagentProject_pages_homeQuery {
rates(currency: "USD") {
currency
rate
}
}
`;
var map__42409 = (reagent_project.pages.home.query.cljs$core$IFn$_invoke$arity$1 ? reagent_project.pages.home.query.cljs$core$IFn$_invoke$arity$1(module$node_modules$react_relay$index.useLazyLoadQuery) : reagent_project.pages.home.query.call(null,module$node_modules$react_relay$index.useLazyLoadQuery));
I can get this:
var query = graphql`
query reagentProject_pages_homeQuery {
rates(currency: "USD") {
currency
rate
}
}
`;
var data = useLazyLoadQuery(query, {});
I had tried to update my shadow-cljs.edn
like so:
:builds {:app {:target :esm
:compiler-options {:optimizations :simple}
:output-dir "resources/public/js"
:asset-path "/js"
:modules {:app {:init-fn reagent-project.core/init!}}}}
:dev-http {3000 {:root "resources/public"
:handler reagent-project.handler/app}}}
it comes from https://www.npmjs.com/package/react-relay
the complete component is:
(defnc home []
(let [{:keys [rates]} (-> useLazyLoadQuery query)]
(let [{:keys [currency rate]} rates]
(d/div {:key currency}
(d/p currency ": " rate)))))
;; (d/span {:class "main"}
;; (d/h1 "Welcome to reagent-project")
;; (d/ul
;; (d/li (d/a {:href (path-for :items)} "Items of reagent-project"))
;; (d/li (d/a {:href "/broken/link"} "Broken link"))))
;; )
(defn home-page []
(helix.core/suspense
{:fallback "loading..."}
($ home)))
(ns reagent-project.pages.home
(:require
[reagent-project.utils.path-for :refer [path-for]]
["react-relay" :refer [useLazyLoadQuery graphql]]
[helix.core :refer [defnc $]]
[shadow.cljs.modern :refer [js-template]]
[helix.dom :as d]
[reagent.core :as reagent :refer [atom]]))
(def query (js-template graphql "
query reagentProject_pages_homeQuery {
rates(currency: \"USD\") {
currency
rate
}
}
"))
(defnc home []
(let [{:keys [rates]} (-> useLazyLoadQuery query)]
(let [{:keys [currency rate]} rates]
(d/div {:key currency}
(d/p currency ": " rate)))))
(defn home-page []
(helix.core/suspense
{:fallback "loading..."}
($ home)))
I mean the likelyhood of some other compiler recognizing the CLJS output is very slim
ah, I see. I was considering using a vite transform plugin with this. but I think I'll use the babel one instead to complete the transform
(defnc home []
(let [result (useLazyLoadQuery query)
{:keys [rates]} result
{:keys [currency rate]} rates]
(d/div {:key currency}
(d/p currency ": " rate))))