This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-29
Channels
- # babashka (64)
- # beginners (60)
- # calva (10)
- # circleci (3)
- # clj-kondo (62)
- # cljdoc (6)
- # clojars (2)
- # clojure (152)
- # clojure-europe (19)
- # clojure-nl (3)
- # clojure-uk (18)
- # clojurescript (50)
- # clojureverse-ops (12)
- # core-async (21)
- # cursive (6)
- # data-science (1)
- # datomic (17)
- # events (14)
- # fulcro (64)
- # graalvm (20)
- # graphql (5)
- # honeysql (14)
- # jackdaw (3)
- # jobs (1)
- # jobs-discuss (22)
- # kaocha (2)
- # lsp (9)
- # luminus (8)
- # malli (30)
- # meander (31)
- # other-languages (1)
- # polylith (8)
- # re-frame (15)
- # shadow-cljs (85)
- # specter (2)
- # sql (11)
- # tools-deps (56)
- # vim (39)
- # vscode (7)
- # xtdb (16)
Hello all! Is there any good resource on publishing a clojurescript library as both a jar & on also on npm (with exports for JS consumption)? When published on clojars is there a way to have the package.json inherited by the project that is using the library?
Hi all.
I have been trying to implement the https://www.npmjs.com/package/paho-mqtt in an ClojureScript app running as a React Native app using https://github.com/PEZ/rn-rf-shadow.
I have gotten it to connect to the MQTT server and I am able to send a message from the client, but when I publish a message on a topic the client is subscribed to it closes the connection and gives me a cryptic error message.
The javascript example for the client describes the onConnectionLost
and onMessageArrived
functions like this:
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) {
console.log("onMessageArrived:"+message.payloadString);
}
and that you set the callback handlers on the client object like this:
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
I setup the connection like this in src/main/example/app.cljs
:
(:require
["react-native" :as rn]
[reagent.core :as r]
[re-frame.core :as rf]
[shadow.expo :as expo]
["paho-mqtt" :as paho]
[example.events]
[example.subs]))
...
(defonce mqtt-client (paho/Client. "127.0.0.1" 8000 "myClientId"))
(defn mqtt-connected [] (.subscribe mqtt-client "World"))
(defn mqtt-on-message [message] (prn str("I have a message for you! " message)))
(defn mqtt-connection-lost [response-object] (prn "mqtt connection lost! " response-object))
(set! (.-onMessageArrived mqtt-client) mqtt-on-message)
(set! (.-onConnectionLost mqtt-client) mqtt-connection-lost)
(.connect mqtt-client #js {:onSuccess mqtt-connected})
When I publish a message to the "World" topic it gives me this from the onConnectionLost
function:
"mqtt connection lost! " #js {:errorCode 5, :errorMessage "AMQJS0005E Internal error. Error Message: fexpr__29213.call is not a function. (In 'fexpr__29213.call(null,message)', 'fexpr__29213.call' is undefined), Stack trace: No Error Stack Available", :reconnect nil, :uri ""}
It seems like the onMessageArrived
function is never called and I don't know why.
The onConnectionLost
function works fine but the onMessageArrived
function does not even though it is registered in the exact same way as the onConnectionLost
function.
Any suggestions?
@hiskennynessA very suspicious line in your code:
(defn mqtt-on-message [message] (prn str("I have a message for you! " message)))
Do you see an issue there?Also, I'm not sure about React Native, but in regular browsers where you have DevTools, you can set a breakpoint on any exception. Quite helpful in such circumstances.
I have tried it by just having it be (prn "fooo")
and nothing changed
But you have (prn str(...
where I think you want (prn (str ...)) @U029L20KBQB
Now that you have switched to (print "foo")
, just make sure that new code is running. 🙂
I checked the Machine_Head client code https://github.com/clojurewerkz/machine_head/blob/master/src/clojure/clojurewerkz/machine_head/client.clj and was struck by the different handling given to message receipt:
(defn ^:private ^IMqttMessageListener reify-message-listener
[delivery-fn]
(reify IMqttMessageListener
(^void messageArrived [this ^String topic ^MqttMessage msg]
(delivery-fn topic (cnv/message->metadata msg) (.getPayload msg)))))
But I know nothing about interop. 🤷You're right about the (prn (str ...))
my mistake.
I relaunch the app from the metro bundler every time I test a new thing (mostly because of the (defonce ...)
and I want to be sure that the client connects again. (I could probably reconnect it using the repl))
So in the end we shifted to https://www.npmjs.com/package/react-native-native-mqtt since that is where we were running and after some more interop learning curve we are up and pub/subbing. @U029L20KBQB can explain better if anyone is curious.
also, what is the representation of string type in clojurescript? can't find it in cljs.core/...
clojure.string assuming you want access to the many string functions.
(defn ^boolean string?
"Returns true if x is a JavaScript string."
[x]
(goog/isString x))
(instance? js/String (js/String. "")) ; => true (instance? js/String "") ; => false string primitive vs string object
java.lang.String
it is a javascript primitive type https://developer.mozilla.org/en-US/docs/Glossary/Primitive https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures
When upgrading from clojurescript v 1.10.764 to 1.10.866 , which notably had 2 goog closure lib upgrades I note with a dev figwheel style build (latest lein-figwheel + cljsbuild) that I suddenly get
Uncaught SyntaxError: Unexpected token '!'
Digging deeper the devtools difference I see in the browser is in the file:
<js-compilation-location>/dev/goog/log/log.js
The odd part is in the old cljs version, this file looked like the direct source JS file from google closure lib. In the new cljs version, it instead showing me some transpiled variant, with a header like this:
/*TRANSPILED*//*
Copyright The Closure Library Authors.
SPDX-License-Identifier: Apache-2.0
*/
Then the actual offending line is here (with the name truncated a bit):
/*TRANSPILED*//*
Copyright The Closure Library Authors.
SPDX-License-Identifier: Apache-2.0
*/
goog.provide("goog.log");
goog.provide("goog.log.Level");
goog.provide("goog.log.LogBuffer");
goog.provide("goog.log.LogRecord");
goog.provide("goog.log.Logger");
goog.require("goog.asserts");
goog.require("goog.debug");
goog.log.Loggable;
goog.log.ENABLED = goog.define("goog.log.ENABLED", goog.debug.LOGGING_ENABLED);
goog.log.ROOT_LOGGER_NAME = "";
var file_$Users$myuser$_m2$repository$org$clojure$google_closure_library$0_0_20201211_3e6c510d$google_closure_library_0_0_20201211_3e6c510d_jar!$goog$log$log$classdecl$var0 = function(name, value) {
this.name = name;
this.value = value;
};
You can see in the long var
name in the transpiled one there is an “!” used in the name. I don’t know that that’s even a legal JS identifier. This looks to be what is reported.
I don’t understand why previously I don’t see this “transpiled” file at all, but with the cljs upgrade now I do. So why it exist now is the first real mystery to me. The second is why it’s producing this invalid name.that looks like an encoded jvm resource url
I actually didn’t think of that. That’s at least something for me to go from. Thanks!
Hey, what would be a good way to create a custom material-ui SvgIcon
component based on an svg files (since shadow-cljs
doesn't support importing assets.)? Would the svg
path attribute behave like the src
attribute and load the contents of a svg file, i.e. <svg path="/path/to/file.svg">
?
[:img {:src "path/to/file.svg" :width 48 :height 48}]
You can use svg in image tags.
The svg "<path ... > " is a different thing. It is used to define the shape of a path.Yea. So an image tag can be used inside a material-ui SvgIcon component?
ahh, that makes more sense.. material-ui SvgIcon... I am not familiar with material ui... Are you using reagent/hiccup?
Just an idea... it says in https://stackoverflow.com/questions/38510443/how-to-use-an-svg-file-in-a-svgicon-in-material-ui (scroll down) that you can use react components in svgIcon . You could try turning your svg into hiccup https://htmltohiccup.herokuapp.com/, then make a reagent component out of it and pass it to SvigIcon.
(defn my-icon-comp
[props]
.....)
[:> SvgIcon
(r/as-element [my-icon-comp {}])
]
also... as you can use react components in svgIcon i guess you can use [:img {:src "path/to.svg"}]
too and load it dynamically. But you loose control over styling the svg... as far as i know.
No need to style it, other than maybe sizing.
Alright, thanks for the suggestions, I'll try them out.
remove width and height from the svg and leave viewBox. that will make it expand to the container. should work.
I think SvgIcon comes with it's own dimentions.
24x24 I think.
This is how I made SVG icons for my Reagent app: https://github.com/askonomm/blocko/blob/master/src/blocko/icons.cljs
(if that helps at all)
yeah, as @U026NQLSBLH points out, maybe just use reagent components and do not use Material's svgIcon..