Fork me on GitHub
#fulcro
<
2022-05-03
>
Quentin Le Guennec09:05:58

Is :body called with a result-handler in a custom fulcro remote special in a way? When I call (result-handler {:body data} , I receive {:body {}} in my default result action, but when I call (result-handler {:any-other-key data}) I receive the excepected data in my default result action.

tony.kay15:05:08

I’d suggest using the source and book when writing these. I don’t remember off the top of my head. I’d have to do the same: look at the book or the source code. That’s why I wrote the book, and why it is open source 😉

tony.kay15:05:25

The basic idea is that you have to send through a body that matches the shape of the normalizing query that was used with the request. If there isn’t one, then you’d have to supply that if you want any data to flow through in a meaningful way, though the middleware and remote are allowed to override that normalizing query.

Quentin Le Guennec08:05:48

Ok, that might help. It's just a REST api though, I don't use any normalizing features of fulcro, just a custom default-result-action that will dispatch depending on the response type.

tony.kay14:05:25

oh, well, then you should be reading the built-in one in detail. That’s a very interesting and sensitive area of the library

tony.kay15:05:29

outgoing: EQL request (which defines the expected shape of the response incoming: map of data that must match EQL request OR must be handled by remote/middleware to make up an EQL request to use for merging

sheluchin16:05:50

I get this error on server startup (`clojure -A:xtdb -M -m com.example.components.server`) unless I include shadow-cljs as a dep:

Syntax error (FileNotFoundException) compiling at (com/fulcrologic/rad/pathom_common.clj:1:1).
Could not locate com/wsscode/common/async_clj__init.class, com/wsscode/common/async_clj.clj or com/wsscode/common/async_clj.cljc on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
Is that normal? I thought I would not need shadow when running the server.

Hukka16:05:59

I don't see how shadow-cljs has anything to do with it, but https://github.com/fulcrologic/fulcro-rad/blob/develop/deps.edn has pathom as deps only in dev profile, and that's needed for the version of async-clj that rad seems to rely on

sheluchin16:05:20

That's true but I have it in my :deps..

Hukka17:05:05

I notice pathom3 but not pathom

sheluchin17:05:42

I need both?

Hukka17:05:58

I don't know about pathom3, but that error comes from a missing file, that is in pathom

sheluchin17:05:08

Hmm, yeah, adding it did fix the error. So how did it work all this time locally without pathom 2 included, and why does it work with shadow in there? Anyway, thanks @U8ZQ1J1RR.

Hukka17:05:32

Not sure what exactly happens when shadow is "in there". Either something adds the file to classpath, or somehow com/fulcrologic/rad/pathom_common.clj is not used then

Hukka17:05:27

Or how is "locally" different from running clojure with the command line arguments you showed

sheluchin17:05:18

Well, if I just include this alias to the command I showed, it works:

:shadow-cljs {:extra-deps                                    
              {thheller/shadow-cljs {:mvn/version "2.16.12"} 
               binaryage/devtools {:mvn/version "1.0.0"}}}   
But otherwise I get the error.

sheluchin17:05:03

Some caching issue maybe :man-shrugging: I tried deleting ~/.m2/ and that didn't fix it.

Hukka17:05:35

Yeah, there can be flakiness with deps and cached classpath, especially with older versions of clojure tools

sheluchin17:05:14

Okay, it works for now. I'll add back pathom back to :deps and leave the rest of the mysteries to resolve for another day 🙂 it works for now and I'll probably gain some insights to figure it out with a bit more time. Thanks again, @U8ZQ1J1RR.

Hukka17:05:19

No problem. The heuristic here would be to check what does the problematic project depend on (rad) or where could a file like that belong to (pretty much just google it, or search in github)

tony.kay19:05:56

Yeah, this is definitely a pathom-related deps issue. Depends on which you intend to use. Both can be on the classpath at the same time. They use diff nses.

tony.kay19:05:33

so, as long as you don’t mix them together, it’s fine. You can technically use them both at the same time, as long as you don’t try to use the artifacts of one with the other.

gratitude-thank-you 1
Jakub Holý (HolyJak)21:05:30

Any tips for getting fulcro-websockets working? I think I set both frontend and backend right but the client is just sending an infinite stream of requests like

GET 
that respond with 200 OK and 0 data and the browser console logs an infinite stream of > DEBUG [taoensso.sente:215] - Bad package: (SyntaxError: Unexpected end of JSON input) > sente.cljc:146 > Uncaught #error {:message "Invalid event", :data {:given :chsk/bad-package, :errors {:wrong-type {:expected :vector, :actual {:type Keyword :value :chsk/bad-package}}}} and the WS tab of the browser does not show any communication. The 200 ok seems to be returned by (fws/wrap-api websockets) b/c if I remove it, I get 404 instead. Is the fws/wrap-api somehow set up wrong, returning an incorrect type of response? My client just has (app/fulcro-app {:remotes {... :ws (fws/fulcro-websocket-remote {})}}) - not much to screw up here...

tony.kay23:05:04

Hey…the docs on the repo should be right…I’ve got a local app I, in fact, just set up with ws…here’s what I’ve got for the application (client-side):

(ns application
  "Holds an atom that can be used to find the application from anywhere. DO NOT
   require *anything* in this ns. It is meant to be used from any other ns, so
   you do not get a circular reference. Initialized in `client.cljs`."
  (:require
    [com.fulcrologic.fulcro.application :as app]
    [com.fulcrologic.fulcro.networking.http-remote :as net]
    [com.fulcrologic.fulcro.networking.websocket-remote :as fws]
    [com.fulcrologic.fulcro.rendering.multiple-roots-renderer :as mroot]
    [com.fulcrologic.rad.application :as rad-app]
    [taoensso.timbre :as log]))

(defmulti push-handler (fn [{:websocket/keys [topic]}] topic))

(defmethod push-handler :default [msg]
  (log/info "Unhandled server push: " msg))

(defonce SPA
  (app/fulcro-app
    (merge
      {:remotes
       {:remote (fws/fulcro-websocket-remote
                  {:push-handler (fn [{:keys [topic msg]}]
                                   (push-handler
                                     (merge {:websocket/topic topic} msg)))})
        :api    (net/fulcro-http-remote
                  {:url                "/api"
                   :request-middleware (rad-app/secured-request-middleware {})})}
       :global-eql-transform (rad-app/global-eql-transform
                               (rad-app/elision-predicate
                                 rad-app/default-network-blacklist))
       :optimized-render!    mroot/render!})))

tony.kay23:05:23

(I’m allowing it to talk both via WS and POST…the latter is good for file upload)

tony.kay23:05:53

this is server-side:

(defstate middleware
  :start
  (let [defaults-config (:ring.middleware/defaults-config config/config)]
    (-> not-found-handler
      (wrap-api "/api")
      (fws/wrap-api websockets)
      ;; Fulcro support for integrated file uploads
      (file-upload/wrap-mutation-file-uploads {})
      ;; RAD integration of forms with binary uploads
      (blob/wrap-blob-service "/files" bs/file-blob-store)
      (server/wrap-transit-params {})
      (server/wrap-transit-response {})
      (wrap-html-routes)
      (wrap-defaults defaults-config))))
which is pretty close to stock template

tony.kay23:05:42

where the websockets component is defined as:

(ns component.websocket (:require
    [mount.core :refer [defstate]]
    [marketplace.components.parser :refer [parser]]
    [taoensso.sente.server-adapters.http-kit :refer [get-sch-adapter]]
    [marketplace.components.websockets.client-tracking :as tracking]
    [com.fulcrologic.fulcro.networking.websockets :as fws]
    [com.fulcrologic.fulcro.networking.websocket-protocols :as wsp]))

(deftype ClientTracker []
  wsp/WSListener
  (client-added [this ws-net cid]
    (swap! tracking/connected-clients conj cid))
  (client-dropped [this ws-net cid]
    (swap! tracking/connected-clients disj cid)))

(defstate websockets
  :start
  (let [ws (fws/start!
             (fws/make-websockets
               parser
               {:http-server-adapter (get-sch-adapter)
                :parser-accepts-env? true
                :sente-options       {:csrf-token-fn nil}}))]
    (wsp/add-listener ws (->ClientTracker))
    ws)
  :stop
  (fws/stop! websockets))

(defn broadcast! [topic msg]
  (doseq [cid @tracking/connected-clients]
    (wsp/push websockets cid topic msg)))

(comment
  (broadcast! :BOO {:x 1}))

lgessler00:05:41

here's my server config in case it's useful: https://github.com/lgessler/glam/blob/master/src/main/glam/server/middleware.clj#L152 I don't remember details but I remember middleware ordering being tricky to get right somehow. Maybe take a look at that if you're out of ideas

👍 1
Jakub Holý (HolyJak)08:05:42

thank you very much! I am 👀 into it...

Jakub Holý (HolyJak)08:05:08

I use Jetty 9. Do you as well?

tony.kay14:05:12

I know jetty is supposed to be the better-maintained one, but I’ve had way more problems with it

Jakub Holý (HolyJak)15:05:57

Thanks! Will try to switch

Patrick Brown15:05:41

It's the same to me. I'm on it.