Fork me on GitHub
#shadow-cljs
<
2020-06-24
>
isak03:06:20

it isn't possible to use shadow-cljs inspect from a clojure (not clojurescript) project, is it?

isak04:06:39

wow it works

David Pham04:06:59

Yep :) you need to start the server only.

David Pham04:06:27

It is really useful as it replace somehow the REBL haha

Casey08:06:40

Is expound compatible with shadow-cljs' :node-test target?

Casey08:06:00

Oh I see, I'm running into this > As of https://github.com/clojure/clojurescript/commit/5f0fabc65ae7ba201b32cc513a1e5931a80a2bf7#diff-c62a39b0b4b1d81ebd2ed6b5d265e8cf, ClojureScript instrumentation errors only contain data and leave formatting/printing errors to the edge of the system e.g. the REPL.

Casey08:06:06

Here's an impl of test/report that uses expounds printer

Casey08:06:49

Now, is it possible to load that in the node-test target without overriding shadow.test.node/main

thheller08:06:07

you can put it into any of your test namespaces

thheller08:06:06

or include it from one or all of them

thheller08:06:18

remove

(nodejs/enable-util-print!)
(enable-console-print!)
though

thheller08:06:37

the code just needs to run before the tests run

Casey08:06:35

that works well thanks

Casey08:06:54

Updated the snippet

thheller08:06:16

actually that doesn't work

thheller08:06:53

(ts/instrument) is a side-effecting macro which needs to be called AFTER everything has been compiled

thheller08:06:02

but you are calling it at a point BEFORE everything is compiled, or maybe partially compiled thus not instrumenting everything

Casey09:06:10

its working for me atm, so must be the luck of compile order? What would be the proper way to fix it? Could I put it at the end of every test file that needs instrumentation ?

thheller09:06:50

I'd go with a custom runner ns

thheller09:06:59

and add the expound stuff and then the (st/instrument) call in main

thheller09:06:10

that ensures that everything is instrumented before tests run

dazld10:06:02

@thheller the new cljs_eval function is really nice! how do you do the lookup between a var in the form and which function to call / value etc?

thheller10:06:57

@dazld I don't understand the question? what lookup?

thheller10:06:49

ah ... I'm just compiling on the server as all the REPLs do. this has basically no logic on the client at all.

👍 3
dazld10:06:09

thought so - i understood vars were elided at compile time

dazld10:06:13

so was wondering how that worked

dazld10:06:36

elided maybe wrong word

thheller10:06:55

yeah this isn't self-hosted. all the compiler stuff happens in the watch worker process on the server.

👍 6
ghaskins12:06:30

Hey all, does anyone know if theres a way to utilize clojure.datafy in a manner that is compatible with optimized output?

ghaskins12:06:15

By this, i mean the symbol renaming problem

thheller12:06:52

not sure what you mean? it works just fine in optimized output?

ghaskins12:06:21

no, i mean it works in dev output but is getting munged in optimized output

ghaskins12:06:47

i wasnt sure if there was a way to annotate/utilize such that the generated code gets enough of a hint to allow datafy to do its thing

thheller12:06:56

I don't know what you mean by that. can you provide an example?

thheller12:06:08

datafy is just as minified as all the rest so its not a problem?

thheller12:06:55

granted you still need to follow externs inference stuff and maybe typehint a bit

ghaskins12:06:59

you and I spoke about this area before, but it was before I knew about datafy, so I was revisiting to see if that could help

ghaskins12:06:03

in short, im working with grpc-web

thheller12:06:32

and you datafy objects from grpc?

ghaskins12:06:42

and im doing things like this

ghaskins12:06:44

(defmacro invoke-unary
  [client method req auth]
  `(p/create
     (fn [resolve# reject#]
       (let [result# (~method ~client
                      ~req
                      (cljs.core/clj->js {"authorization" ~auth})
                      (fn [err# resp#]
                        (if err#
                          (reject# err#)
                          (resolve# (datafy (.getMessage ^js resp#))))))]
         (.on result# "status" (fn [status#]
                                 (let [s# (datafy ^js status#)]
                                   (when-not (zero? (:code s#))
                                     (reject# s#)))))))))

ghaskins12:06:17

which works in dev, for instance, i see things like

ghaskins12:06:28

core.cljs:159 ERROR [mcp-admin-ui.events:20] - fetch-providers failed: {"code" 16, "details" "invalid auth token", "metadata" #js {:cache-control "private, no-cache", :connection "keep-alive", :content-length "0", :content-type "application/grpc-web-text+proto", :date "Wed, 24 Jun 2020 12:09:43 GMT", :grpc-message "invalid auth token", :grpc-status "16", :server "istio-envoy", :x-envoy-upstream-service-time "1"}}

ghaskins12:06:39

but in optimized, I just get

ghaskins12:06:53

TypeError: Z.og is undefined

thheller12:06:57

why is this a macro? 😛

mauricio.szabo15:06:37

@thheller can I ask why it's not the default? Everytime I start a new project, I add infer-externs because I find it extremely useful 🙂

thheller16:06:40

yeah it maybe should be at this point 😛

ghaskins12:06:48

because I need to capture the dot-form interop

ghaskins12:06:14

i couldnt figure out how to do that without a macro

thheller12:06:16

in this case it likely is the .on being renamed

ghaskins12:06:28

cool, i will check that

thheller12:06:19

and maybe the method stuff? how do you use invoke-unary?

thheller12:06:53

^js result# might be enough

ghaskins12:06:15

its called like this

ghaskins12:06:16

(defn get-providers [auth]
  (let [req (pb/ProvidersGetRequest.)]
    (.setHeader req (utils/make-header))
    (invoke-unary (connect) .getProviders req auth)))

ghaskins12:06:24

(the grpc-web lib is terrible

ghaskins12:06:52

its super awkward to interface with

thheller12:06:11

yeah ok that s the other problem then

ghaskins12:06:11

ill try the result$ suggestion, too

thheller12:06:22

.getProviders also needs a hint

thheller12:06:43

but ^js .getProviders might not work

thheller12:06:07

but datafy isn't the problem here its usual JS interop thats the problem

ghaskins12:06:34

i didnt mean to suggest otherwise

thheller12:06:36

use shadow-cljs release app --pseudo-names. that will give a better idea of what Z.og is

ghaskins12:06:09

i just wasnt sure if there was some magic "oh yeah, do this to make datafy work"

ghaskins12:06:19

(which, i think is what we are working through now)

ghaskins12:06:20

not sure this is overkill/correct, but going to try this now

ghaskins12:06:21

diff --git a/src/cljs/mcp_admin_ui/grpc/macros.clj b/src/cljs/mcp_admin_ui/grpc/macros.clj
index 344cc97..0f6d050 100644
--- a/src/cljs/mcp_admin_ui/grpc/macros.clj
+++ b/src/cljs/mcp_admin_ui/grpc/macros.clj
@@ -6,14 +6,14 @@
   [client method req auth]
   `(p/create
      (fn [resolve# reject#]
-       (let [result# (~method ~client
-                      ~req
-                      (cljs.core/clj->js {"authorization" ~auth})
-                      (fn [err# resp#]
-                        (if err#
-                          (reject# err#)
-                          (resolve# (datafy (.getMessage resp#))))))]
-         (.on result# "status" (fn [status#]
-                                 (let [s# (datafy status#)]
-                                   (when-not (zero? (:code s#))
-                                     (reject# s#)))))))))
+       (let [result# (^js ~method ^js ~client
+                       ~req
+                       (cljs.core/clj->js {"authorization" ~auth})
+                       (fn [err# resp#]
+                         (if err#
+                           (reject# err#)
+                           (resolve# (datafy (.getMessage ^js resp#))))))]
+         (.on ^js result# "status" (fn [status#]
+                                     (let [s# (datafy ^js status#)]
+                                       (when-not (zero? (:code s#))
+                                         (reject# s#)))))))))

thheller12:06:40

^js ~method that won't do anything

ghaskins12:06:52

have to do it at the callsite?

thheller12:06:47

no you can do it in the macro but ~method becomes (unquote method) so you have ^js (unquote method) which is not the place you need it in

thheller12:06:11

~(vary-meta method assoc :tag 'js) might work

thheller12:06:49

try the --pseudo-names first to actually figure out where the issue is

ghaskins12:06:53

you are a ninja...i wouldnt have thought to try that, heh

thheller12:06:54

no point in hinting blindly

ghaskins12:06:10

i ran lein shadow release app --pseudo-names but nothing is jumping out at me to see if it did anything

ghaskins12:06:27

is that the wrong incantation?

ghaskins12:06:26

or could that be the hint that I captured all the annotations i needed?

thheller12:06:36

I don't know if lein shadow supports that arg

thheller12:06:05

TypeError: Z.og is undefined this should be different. if its not then the arg was passed properly

ghaskins12:06:28

its the same, so let me try the direct method

ghaskins12:06:43

also, do you have a similar flow as "watch app" but for a release build?

ghaskins12:06:04

its painful for me to iterate on release through docker ->k8s

ghaskins12:06:28

i need the dev-http proxy to test locally, is the problem

ghaskins12:06:35

maybe i just need an alternate config

ghaskins13:06:22

ok, i added a parallel config, for now

ghaskins13:06:24

:shadow-cljs {:nrepl {:port 8777}
                :dev-http {8280 {:root "resources/public"
                                 :proxy-url ""}}
                :builds {:app {:target :browser
                               :compiler-options {:infer-externs :auto}
                               :output-dir "resources/public/admin/js/compiled"
                               :asset-path "/admin/js/compiled"
                               :modules {:app {:init-fn mcp-admin-ui.core/init}}}
                         :rel {:target :browser
                               :compiler-options {:infer-externs :auto
                                                  :optimizations :advanced}
                               :output-dir "resources/public/admin/js/compiled"
                               :asset-path "/admin/js/compiled"
                               :modules {:app {:init-fn mcp-admin-ui.core/init}}}}}

ghaskins13:06:03

however, watch rel still results in a bunch of independent js, so I think im not quite doing what i expected

thheller13:06:37

shadow-cljs server and leaving that running. then shadow-cljs release app is quicker. no clue about your docker setup or lein shadow though. I do not recommend lein shadow because it makes all of this harder.

ghaskins13:06:52

awesome, ill try that

thheller13:06:06

watch does not run optimizations at all ever so setting it does nothing. :rel is identical to :app basically as the default is :optimizations :advanced anyways

ghaskins13:06:23

shadow-cljs server was the magic I needed

ghaskins13:06:06

now i can iterate quick, let me add that --psuedo-names option and see what I get

ghaskins13:06:41

Uncaught TypeError: Cannot read property '$datafy$' of undefined
    at Array.<anonymous> (app.js:33921)
    at zb (app.js:2042)
    at Ma.<anonymous> (app.js:2041)
    at xa (app.js:2026)
    at ra (app.js:2026)
    at vb (app.js:2034)
    at Ma.O (app.js:2062)
    at Ma.K (app.js:2062)

ghaskins13:06:10

and actually, i see this in this build mode

ghaskins13:06:11

File: /Users/ghaskins/sandbox/git/mcp-admin-ui/src/cljs/mcp_admin_ui/grpc/account_service.cljs:14:5
--------------------------------------------------------------------------------
  11 | (defn get-providers [auth]
  12 |   (let [req (pb/ProvidersGetRequest.)]
  13 |     (.setHeader req (utils/make-header))
  14 |     (invoke-unary (connect) .getProviders req auth)))
-----------^--------------------------------------------------------------------
 Use of undeclared Var clojure.datafy/datafy

ghaskins13:06:16

probably related

ghaskins13:06:05

so, im borking up the requires on datafy, somehow

ghaskins13:06:05

hmm, im not getting something

ghaskins13:06:51

i tried using a fully qualified (clojure.datafy/datafy) form, but its still unhappy with me calling that in optimized mode

ghaskins13:06:58

works fine in debug mode

ghaskins13:06:30

im not quite sure what would cause that

ghaskins13:06:18

oh, maybe this is simply that the value is nil

ghaskins14:06:53

im out of ideas...i added a js/console.log just prior and the object seems to be valid

ghaskins14:06:07

heres the log output

ghaskins14:06:09

status: {code: 16, details: "invalid auth token", metadata: {…}}
app.js:33922 Uncaught TypeError: Cannot read property '$datafy$' of undefined
    at Array.<anonymous> (app.js:33922)
    at zb (app.js:2042)
    at Ma.<anonymous> (app.js:2041)
    at xa (app.js:2026)
    at ra (app.js:2026)
    at vb (app.js:2034)
    at Ma.O (app.js:2062)
    at Ma.K (app.js:2062)

ghaskins14:06:33

for

(.on ^js result# "status" (fn [status#]
                                     (js/console.log "status:" status#)
                                     (let [s# (datafy status#)]
                                       (when-not (zero? (:code s#))
                                         (reject# s#)))))

ghaskins14:06:57

ok, i figured it out (sorta)

ghaskins14:06:44

it has something to do with clojure.datafy/datafy...even though that exists in both clj and cljs, i think its somehow not recognized in the macro expansion when in release build

ghaskins14:06:02

i switched to cljs.core/js->clj and this of course has no ambiguity

thheller14:06:41

thats a weird error. do you call .datafy somewhere? using datafy otherwise does not create a datafy property since its a protocol?

ghaskins16:06:37

no, its super weird

ghaskins16:06:18

im speculating but it seems like its confused over the dual definition

ghaskins16:06:54

in summary, both ["datafy" "js-cljs"] throw erros about the var not existing within the macro ns (even though i had referred it in the macro ns)....making datafy fully qualified explicitly as clojure.datafy/datafy still results in a undefined var, and cljs.core/js->clj works

ghaskins16:06:08

but only for release builds...dev builds work in all forms

ghaskins16:06:31

this is the only one that works in release

ghaskins16:06:32

(.on ^js result# "status" (fn [status#]
                                     (let [s# (cljs.core/js->clj status# :keywordize-keys true)]
                                       (when-not (zero? (:code s#))
                                         (reject# s#)))))

ghaskins16:06:12

its entirely possible I have some subtle expansion error in my macro that ive yet to uncover

ghaskins16:06:54

just to confirm, I also dropped the :refer approach and did (:require [clojure.datafy :as d]) and (d/datafy)

thheller16:06:12

I still think you are looking at the wrong code

dpsutton16:06:15

could this be a clojure.datafy vs cljs.datafy problem?

ghaskins16:06:18

but it still shows up as undefined clojure.datafy/datafy at compile time

ghaskins16:06:46

let me try that

thheller16:06:49

no, its clojure.datafy

thheller16:06:54

there is no cljs.datafy

ghaskins16:06:02

i had hope for a second there

thheller16:06:25

you should still try to identify what $datafy$ actually is

thheller16:06:43

you are quite possibly will tweaking the wrong bit of code

ghaskins16:06:55

any advice on how to do that?

thheller16:06:03

or did you confirm that its 100% what you are working on now?

thheller16:06:19

I usually just look at the compiled pseud-names output

thheller16:06:36

just look for .$datafy$ and figure out what that is 😛

ghaskins16:06:44

looking now

thheller16:06:23

or in chrome "pause on uncaught exception" and debug from there

thheller16:06:43

shadow-cljs release app --debug gives you pseudo-names + source maps which makes that easier

ghaskins16:06:12

awesome, ill try both of those too

ghaskins16:06:55

I dont really have the full context/knowledge to know whats right, but if I had to guess, the issue is simply that the gensym'd symbol isnt datafy-able ?

thheller16:06:20

hmm that is indeed the code you are working on

ghaskins16:06:25

actually, it looks like two gensymed symbols were munged?

thheller16:06:30

but it should not be renamed that way. makes no sense.

thheller16:06:43

do you have manually specified clojure and datafy as externs?

ghaskins16:06:57

not to my knowledge

thheller16:06:58

hmm no they are renamed so its not externs

thheller16:06:08

but they should be flattened. not sure why it doesn't flatten them

thheller16:06:41

oh wait .. how did you setup your macro? do you actually require clojure.datafy in CLJS code?

ghaskins16:06:56

nope...i can try that

ghaskins16:06:40

i was actually reading that this morning, heh

ghaskins16:06:43

i'll re-review

ghaskins16:06:59

i actually had trouble with one of your suggestions

ghaskins16:06:08

(the dual clj/cljs ns didnt work for me

ghaskins16:06:26

maybe that is another hint

thheller16:06:33

sounds like it

ghaskins16:06:59

i was only able to get it to work with a single .clj + :require-macros in the consumer, but only in dev mode

ghaskins16:06:22

adding a dual .cljs would not compile for me

thheller16:06:45

then you are definitely doing something incorrectly there

ghaskins16:06:34

ok, progress

ghaskins16:06:07

adding the :require to the consumer got rid of both the :undeclared-var warning at compilation, and the $datafy$ TypeError at runtime

ghaskins16:06:21

ty for that

ghaskins16:06:53

ultimately it looks like datafy is limited in :advanced mode, now

ghaskins16:06:58

core.cljs:159 ERROR [mcp-admin-ui.events:20] - fetch-providers failed: [object Object]

ghaskins16:06:11

instead of the decoded fields

ghaskins16:06:20

maybe that is par for course

ghaskins16:06:55

i guess the only weird thing left is that datafy and js->clj both return a map in dev, but only js->clj returns one in :advanced

ghaskins16:06:51

(the operative part of the log is the [object Object]

thheller16:06:34

wait ... you had an undeclared-var warning the entire time?

ghaskins16:06:51

yeah, i mentioned that though

thheller16:06:09

hmm yeah I missed that ...

thheller16:06:28

I don't know what fetch-providers is but I assure you datafy works just fine in :advanced

ghaskins16:06:28

This is what that log should have looked like if it worked

ghaskins16:06:31

core.cljs:159 ERROR [mcp-admin-ui.events:20] - fetch-providers failed: {:code 16, :details "invalid auth token", :metadata {:date "Wed, 24 Jun 2020 16:58:04 GMT", :server "istio-envoy", :grpc-status "16", :x-envoy-upstream-service-time "2", :cache-control "private, no-cache", :content-length "0", :grpc-message "invalid auth token", :content-type "application/grpc-web-text+proto", :connection "keep-alive"}}

thheller16:06:45

it is 100% your code being the problem. not datafy.

ghaskins16:06:46

oh, im sure its me

ghaskins16:06:56

i just dont understand whats wrong

thheller17:06:19

I don't know either. Don't have enough code to make sense of any of this.

ghaskins17:06:55

ill see if I can put a test-case together

Adrian Smith20:06:23

Has any one ever got https://chakra-ui.com/getting-started working under shadow-cljs? I can get it working with React but with shadow no dice :S

Adrian Smith21:06:25

I was missing empty maps as the attributes for the components