Fork me on GitHub
#shadow-cljs
<
2020-04-29
>
thheller07:04:48

@jayzawrotny one guess would be that it tries to eval stuff even when no runtime (eg. browser) is connected to do the actual eval?

Eccentric J16:04:20

I don't think it's that as I'm getting the error when running a node process while connected to the REPL. Sounds like it's not obvious so the maintainer will likely need to find time to debug.

Eccentric J17:04:57

@thheller We've examined the stack-trace more carefully and found the issue is due to this function returning false. https://github.com/rksm/clj-suitable/blob/master/src/main/suitable/complete_for_nrepl.clj#L204-L205 Anything stick out there?

kucerm210:04:41

Hi, is possible that shadow-cljs exclude .scss.js* node module files from target build?

thheller10:04:40

why would it? I mean actual .js files should load without issue?

kucerm211:04:42

I'm trying fluent-ui and get this errors with this require

kucerm211:04:25

(ns app.main
  (:require [reagent.core :as r]
            ["@fluentui/react" :refer [Button PrimaryButton Stack]]
            ["@uifabric/utilities/" :as fu]
            ["@uifabric/styling/" :as fs]))

thheller11:04:27

right so thats an actual .scss require

kucerm211:04:56

in CalendarDay,js is this

kucerm211:04:00

import * as stylesImport from './Calendar.scss';

thheller11:04:25

yeah, usually libraries ship with those either removed completely or already converted to .js

thheller11:04:40

so the lib seems to presume that you are using webpack with a scss loader configured?

thheller11:04:47

that won't work with shadow-cljs

kucerm211:04:35

Ah, that's unfortunate

thheller11:04:20

you can use webpack if you want but you'll have to set that up on your own

thheller11:04:47

its 2 line of config for shadow-cljs but no clue how to do the webpack parts 😛

kucerm211:04:54

for completeness the file contains

kucerm211:04:32

/* tslint:disable */
import { loadStyles } from '@microsoft/load-themed-styles';
loadStyles([{ "rawString": ".root_d7ec3e0f{-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:none;box-shadow:none;margin:0;padding:0}.root_d7ec3e0f *{overflow:visible}.root_d7ec3e0f *::-moz-focus-inner{border:0}.root_d7ec3e0f *{outline:transparent}.root_d7ec3e0f *{position:relative}.ms-Fabric--isFocusVisible .root_d7ec3e0f *:focus:after{content:'';position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;border:1px solid " }, { "theme": "neutralSecondary", ...

kucerm211:04:44

Calendar.scss.js

thheller11:04:49

so it is compiled? you are confusing me here

kucerm211:04:29

sorry I never use webpack and scss.js file see first time

thheller11:04:11

ah ok, now I get it.

thheller11:04:24

var stylesImport = require("./Calendar.scss"); this is the issue

thheller11:04:51

it is in the office-ui-fabric-react npm package

thheller11:04:57

the first warning you get

thheller11:04:01

seems like that is badly packaged?

kucerm211:04:23

this import is in @fluentui/react/lib/Calendar.js

export * from 'office-ui-fabric-react/lib/Calendar';
and office-ui-fabric-react package is in node_modules directory

thheller11:04:15

yes exactly. that is the bad package not @fluentui/react

thheller11:04:38

CalendarDay.js is the bad one, not sure if there are others

thheller11:04:08

yep there are others

thheller11:04:24

the entire lib uses that. probably best to report that as a bug

kucerm211:04:40

No, CalendarDay.js is in right path

kucerm211:04:45

sry bad directory 🙂

thheller11:04:47

you are in the wrong dir

thheller11:04:16

hmm actually you are right

thheller11:04:22

the files do actually exist

thheller11:04:31

so this should work

thheller11:04:30

ah yeah I think I know what happens

thheller11:04:34

yeah thats a bug in shadow-cljs

kucerm211:04:43

It's possible to get workaround it?

thheller11:04:05

will need to think about that for a bit

thheller11:04:16

no quick hack other than using webpack

kucerm212:04:02

Ok, thank you very much for your interest. I wait until you have an solution, you are shadow-walker 🙂

thheller12:04:28

first time I see a package using this method it would go away if the require in those files just used require("./Calendar.scss.js") but I guess they had to rely on that little bit of extra magic 😛

thheller12:04:04

I guess thats a quickfix if you want one

kucerm212:04:12

It's M$ product in TS 🙂

thheller12:04:33

for all files in that lib just search&replace .scss") with .scss.js") 😛

kucerm212:04:59

no problem it's only 100+ files 🙂 It not terrible for my tests 😉

thheller12:04:32

one command in your editor 😉

kucerm212:04:50

I love it 😄

thheller12:04:03

I'll see if I can sort this out easily. the filtering I did for css is a bit naive anyways

kucerm212:04:46

I thought that *.scss is not a coincidence

thheller12:04:51

yeah first time I see the combination of actually keeping the .scss require and just expecting to pick up the .scss.js

thheller12:04:07

normall either the require is renamed or uses the full name or just removed

kucerm212:04:09

Program run without error, after rename, thank you 😉

Joel Söderman14:04:17

Hi! I’m using shadow-cljs and loving it. Thanks so much for doing this! I have a question: is there a convenient a way to run just one specific test from the command line?

thheller14:04:51

not yet. the testing has been neglected for a bit but I have some plans to make that a bit more convenient.

thheller14:04:10

you can use a REPL though

Lucy Wang14:04:12

some time I have written some custom runner code for that

Lucy Wang14:04:21

in a project with target :node-script

thheller14:04:34

shadow-cljs node-repl (require 'your.test-ns) (your.test-ns/the-test-you-want)

thheller14:04:03

thats what I do ... from my editor REPL though not from the command line

Lucy Wang14:04:49

@thheller the cmd you give won't run fixtures, would it?

thheller14:04:41

not actually sure. might need to go through cljs.test for that

Joel Söderman14:04:40

Thanks for your quick responses 🙂 I will play around with you suggestions!

tetriscodes18:04:00

Anyone get prepl working with shadow-cljs? Or can point me in the right direction

tetriscodes18:04:22

Using vim conjure and setting :prepl {:app 5557}} and when conjure tries to connect, I get a Stream Closed: http://java.io.IOException

Olical18:04:29

I never managed to get prepl to work nicely with Conjure I'm afraid, it requires a few more patches to shadow-cljs (and every other prepl implementation tbh)

Olical18:04:45

You'll probably have better luck with Conjure's new develop branch which uses nREPL and works with shadow-cljs REALLY well.

Olical18:04:21

You get completion and go to def too 😄 same key bindings, no pre-compile step, :help based docs. It's a lot better.

tetriscodes19:04:26

Awesome. So dev branch supports prepl and nrepl going forward?

Olical19:04:10

Just nREPL today, but prepl is on my roadmap. The prepl won't be as feature rich, but I hope to add some support for it.

Olical19:04:31

Continuing conversation in the #conjure channel since this is Conjure specific really.

tetriscodes19:04:58

Doesn’t master support prepl?

yenda19:04:02

is there a way to prevent objects like goog.i18n.NumberFormatSymbols_en to be advanced compiled?

thheller20:04:38

@yenda you mean the object name itself or the object keys/vals?

yenda06:04:48

The object key/values

yenda06:04:31

I require it in the require, then I want to update a key after js->clj but it's advanced compiled

thheller10:04:26

and just list the property names, then it shouldn't rename those and allow swapping?

thheller10:04:57

I'm not actually sure how google handles localization. there is a bunch of stuff already built-in so there should be ways to get this done

thheller10:04:08

I haven't looked into it much

yenda10:04:06

ok thanks yeah it does we just have a special case where we want to format a currency number but without adding the symbol to the formatting

Patrick Truong21:04:38

Hello all, I’m working on setting up re-frame-10x with my project. However, it is not registering my app-db (I can inspect _frame.db.app_db.state and see my re-frame db) in my re-frame-10x tool. I know using shadow-cljs with this library required some extra configs so I followed the sample for conduit project as closely as I could: https://github.com/jacekschae/conduit-re-frame-10x-demo/blob/master/shadow-cljs.edn However, for their shadow-cljs.edn, this is their :modules setup:

:modules          {:main {:entries [devtools.preload
                                      day8.re-frame.trace.preload
                                      conduit.core]}}  
but my shadow-cljs.edn looks like this:
{:deps   true
 :builds {:app {:target     :browser

                :output-dir "public/out"

                :asset-path "/out"

                :modules    {:main {:init-fn alpha-journal.core/main}}

                :compiler-options {:closure-warnings {:global-this :off}
                                   :closure-defines {"goog.DEBUG" true
                                                     "re_frame.trace.trace_enabled_QMARK_" true
                                                     "_frame.tracing.trace_enabled_QMARK_" true}
                                   :optimizations :whitespace}

                :devtools   {:http-root "public"
                             :http-port 8020
                             :after-load alpha-journal.core/main
                             :preloads  [devtools.preload
                                         day8.re-frame-10x.preload]}}}}
How can I setup my preloads while using my :init-fn? Is this possible?

thheller21:04:48

that project is setup as a demo of re-frame-10x using a release build setup so don't use it as an example for a regular project

thheller21:04:15

you config looks correct

thheller21:04:50

not sure what you mean by :init-fn? how is that related?

Patrick Truong21:04:20

@thheller so currently I’m not getting any info in my dashboard for my app-db. My first thought is that I wasn’t using the

[devtools.preload
day8.re-frame.trace.preload]
because I omitted using :entries for :init-fn . I’m not sure if that is the reason for my dashboard not picking up on my app-db or something else

thheller21:04:40

sorry I don't quite understand what your issue is. :init-fn is effectively the same as you specifying :entries [alpha-journal.core] it makes no difference as far as re-frame-10x is concerned?

thheller21:04:06

and the preload ensures it is running before the init so I don't really know what you are asking about here?

thheller21:04:25

(I also don't use re-frame-10x so probably better to ask someone that does)

Patrick Truong21:04:18

To clarify why I thought :init-fn might be problematic in my case, the example case has the vector:

:entries 
[devtools.preload
 day8.re-frame.trace.preload
 conduit.core]
but my case I only include my run function :init-fn: alpha-journal.core/main so I don’t explicitly call for any preloads except in the devtools (which is only when it hot reloads?). This could be completely unrelated to my problem, but it was the one that seemed most potentially problematic since I figure I wasn’t loading the preloads. My then question was how can I load preloads while using :init-fn rather than :entries. Back on your comment saying that the conduit app is a release example. Does that mean I don’t need the :compiler-options and :preloads in :devtools if I were to create a minimum working example? According to this doc, it seems like shadow-cljs doesn’t require any extra config? Is that true? https://github.com/day8/re-frame-10x/blob/master/docs/Advanced-Setup.md Thanks for all the help @thheller! I will ask the re-frame channel if this has nothing to do with my shadow-cljs settings

thheller21:04:09

your setup is correct

thheller21:04:19

:preloads is a way to add entries for development only

thheller21:04:41

so in development your :entries are literally what you just posted

👍 1
thheller21:04:10

oh wait I remember something

thheller21:04:29

I think this has something to do with using rf/dispatch in your :init-fn

thheller21:04:50

so your first dispatch is async and then 10x doesn't pick it up or so

thheller21:04:09

so if you do a dispath in your :init-fn try switching it to dispatch-sync instead\

Patrick Truong21:04:28

Hmm that’s strange since I already should be using that one:

(ns alpha-journal.core
  (:require
   [reagent.core :as r]
   [reagent.dom :as dom]
   [re-frame.core :as rf]
   [alpha-journal.events]
   [alpha-journal.views :refer [app]]))

(defn render
  []
  (dom/render [app]
              (js/document.getElementById "app")))

(defn main
  []
  (rf/dispatch-sync [:initialize])
  (render))

thheller21:04:49

ok then I have no clue sorry

thheller21:04:59

maybe try dispatch instead, maybe it was the reverse

thheller21:04:03

or maybe try

(defn main
  []
  (js/setTimeout
    (fn []
      (rf/dispatch-sync [:initialize])
      (render))
    100))

thheller21:04:34

I vaguely remember something about timing issues but not really sure anymore. long time ago.

Patrick Truong21:04:17

Okay so I found some things that might be related to shadow-cljs. So this were my steps to get it working: 1. I loaded my app (re-frame-10x shows nothing) 2. I made a change to a view file and saved 3. Hot reloaded 4. My app now shows the db in re-frame-10x

Patrick Truong21:04:29

I’m going to try the setTimeout now as well

Patrick Truong21:04:28

setTimeout didn’t work. I’m just curious if the hot reloads are running something that my first load isn’t

thheller21:04:02

maybe increase the timeout? I don't have a clue how long 10x takes to initilaize

thheller21:04:19

try 2000 just to rule out thats not the problem

Patrick Truong21:04:33

Yeah I tried with 10000 and it doesn’t work

thheller21:04:04

ok then I have no clue. as someone that actually knows how this is supposed to work. 😛

thheller21:04:57

ignore the default docs .. the only difference you have in shadow-cljs is that you don't specify a :main but instead have :modules with a :init-fn

👍 1
Patrick Truong21:04:26

Haha, @thheller thanks for the help and clarifying about the docs 🙂. I’ll see if I could figure something out and ask around as well

Patrick Truong21:04:50

I’ll check that out, thanks

Patrick Truong22:04:38

@thheller earlier, I mentioned this briefly: > Back on your comment saying that the conduit app is a release example. Does that mean I don’t need the :compiler-options and :preloads in :devtools if I were to create a minimum working example? To clarify, are the :compiler-options settings only for releasing an app? ex. 

:compiler-options {:closure-warnings {:global-this :off}
                                   :closure-defines {"goog.DEBUG" true
                                                     "re_frame.trace.trace_enabled_QMARK_" true
                                                     "_frame.tracing.trace_enabled_QMARK_" true}
                                   :optimizations :whitespace}
Thanks for explaining this all to a beginner like me 🙇

sergey.shvets22:04:12

Hi! What is the best way to deal with the runtime config in shadow-cljs? E.g. I want to pass different firebase credentials depends on where I deploy. Thanks in advance!

Spaceman22:04:22

So I have a promise in a test like so:

(deftest login-test
  (day8.re-frame.test/run-test-async
   (testing "login test"
     (async done
            (go
              (let [_ (<p! (js/Promise. (see/landing!)))

                    ]
                (prn "done")
                )
              )
            (done)
            )
     )
   )
  )
And running this test just hangs. What do you think is causing this?  Oh yeah, I'm also getting this error on evaluating just the js/Promise part, but have no clue what it means:
TypeError: Promise resolver #<cmp> is not a function
TypeError: Promise resolver #<cmp> is not a function
    at new Promise (<anonymous>)
    at eval (eval at shadow$cljs$devtools$client$browser$global_eval (), <anonymous>:1:2)
    at eval (<anonymous>)
    at Object.shadow$cljs$devtools$client$browser$global_eval [as global_eval] ()
    at eval ()
    at Object.shadow$cljs$devtools$client$env$repl_call [as repl_call] ()
    at Object.shadow$cljs$devtools$client$browser$repl_invoke [as repl_invoke] ()
    at shadow$cljs$devtools$client$browser$handle_message ()
    at eval ()
    at Object.shadow$cljs$devtools$client$env$process_next_BANG_ [as process_next_BANG_] ()

sergey.shvets22:04:52

You need to call (done) function when your async code finished. Here is the good section if you use core.async https://github.com/wilkerlucio/wsscode-async#javascript-async-tests

sergey.shvets22:04:29

The problem with your code is most likely that async macro accepts only two arguments and your (done) call is 3rd arg, but I can't check it right now.

sergey.shvets22:04:33

If you move your (done) inside the (go) block it should work.

Spaceman22:04:29

@U4EFBUCUE Now there's no error, but it just hangs at "testing my.namespace"

Spaceman22:04:41

"done" isn't printed

sergey.shvets22:04:33

is your promise ever resolved?

sergey.shvets22:04:52

<p!
will wait for promise to be resolved or rejected before continuing

Spaceman22:04:07

how would I know?

sergey.shvets22:04:41

what is see/landing! doing?

Spaceman22:04:49

evaluating that promise part gives me this though:

TypeError: Promise resolver #<cmp> is not a function
    at new Promise (<anonymous>)
    at eval (eval at shadow$cljs$devtools$client$browser$global_eval (), <anonymous>:1:118)
    at eval (eval at shadow$cljs$devtools$client$browser$global_eval (), <anonymous>:7:3)
    at eval (<anonymous>)
    at Object.shadow$cljs$devtools$client$browser$global_eval [as global_eval] ()
    at eval ()
    at Object.shadow$cljs$devtools$client$env$repl_call [as repl_call] ()
    at Object.shadow$cljs$devtools$client$browser$repl_invoke [as repl_invoke] ()
    at shadow$cljs$devtools$client$browser$handle_message ()
    at eval ()

sergey.shvets22:04:48

Try:

(-> (js/Promise. (see/landing!)
    (.then (fn [res] <some print>))
    (.catch (fn [err] <some other print>)))

sergey.shvets22:04:07

Oh, wait, I know what the problem is: (js/Promise. (fn [resolve reject] <your code that need to call either resolve or reject> )

sergey.shvets22:04:52

disregard the message with threading macro above, it will show you the same error

Spaceman22:04:31

but see/landing is supposed to return nil

Spaceman22:04:37

@U4EFBUCUE, I don't quite understand what you mean. Would you give a full example how I would run these two functions sequentially in the test: (f1) (f2) where f1 returns nil?

sergey.shvets23:04:21

is see/landing async? Based by name I assume so.

sergey.shvets23:04:43

If it is async, then you need to somehow let your test know that it finished working. You can do this by either having this function return async.core channel and function will post a value on the channel. It will look like this:

(deftest test-async
   (async done
      (go
        (is (= (<! (see/landing!) nil))
        
        (done))))

sergey.shvets23:04:43

Alternatively, you can pass callback to the see/landing and let it call it once it is done:

(deftest test-async
  (async done
     (let [callback #(done)]
        (see/landing! callback))

sergey.shvets23:04:10

or with a promise:

(deftest test-async
  (async done
     (let [_ (<p! (js/Promise. (fn [resolve reject] (see/landing! resolve reject))) ]
        (done))

sergey.shvets23:04:32

(parens) might be off since I'm typing it directly in chat

sergey.shvets23:04:22

In last two cases (see/landing!) must call the callback it gets passed as an argument

Spaceman23:04:30

What about if I have something that follows this see/landing! function that I want to execute after see/landing?

Spaceman23:04:04

This didn't evaluate the second function as expected:

(deftest test-async
  (async done
         (go
           (<! (see/landing!))
           (<! (interact/click-login-btn))
               (done))))

Spaceman23:04:44

i.e., interact/click-login-btn

sergey.shvets23:04:51

So, <! is an operation that takes from channel. go block will wait until something is posted on the channel to resume code that follows. If you want a sequential operation execution you need to make sure that you post/read from the same channel. It is hard to explain in a message. I recommend reading this to get yourself more familiar with core.async: https://www.braveclojure.com/core-async/

sergey.shvets23:04:20

But reading between the lines, it looks like you're trying to make a UI test that will wait for the landing page to load and then run something

sergey.shvets23:04:46

What do you use to load your landing page? Most likely it returns promise that you can chain your checks to.

Spaceman08:04:48

I'm using the react-testing-library's render function to mount the component to the dom. After some familiarity with the async I have the following simple test:

(deftest test-async

  (let [result (waitFor (+ 1 2)) ]
    (async done
           (go
             (is (= 3 (<p! result)))
             (prn "done")
             (done)
             )
           )
    
    ))
waitFor is a react-testing-library function that returns a promise. But this gives me the following error:
ERROR in (test-async) (Error:NaN:NaN)
expected: (= 3 (<p! result))
  actual: #error {:message "Promise error", :data {:error :promise-error}, :cause #object[TypeError TypeError: Cannot read property 'current' of undefined]}
"done"

sergey.shvets15:04:58

It looks like the promise is rejected with an error. I'm not familiar with waitFor and what it does.