fulcro

janezj 2024-10-02T15:55:01.259279Z

I have problems with with some data types and transit. There are some similar questions in this channel, but I don't understand how to solve it in my case. Here is the example of resolver. I understand that java.time.Instant need own serializer. But BigInteger and BigDecimal are not properly deserialized and are displayed as [TaggedValue f, n

(pc/defresolver foo [env params]
  {::pc/output  [{:foo [:foo/bint]}]}
  {:foo #:foo{:bint (java.math.BigInteger. "0")
              :ts  (java.sql.Timestamp. 0)
              :dt (java.util.Date. 0)
             ; Instant is not transit compatible? 
             ; :inst (.toInstant (java.util.Date. 0))
              :int 1
              :float 0.1
              :bdec (java.math.BigDecimal. 0)}})
In Fulcro inspect
{:foo
 {:foo/bint #n 0,
  :foo/ts #inst "1970-01-01T00:00:00.000-00:00",
  :foo/dt #inst "1970-01-01T00:00:00.000-00:00",
  :foo/int 1, 
  :foo/float 0.1, 
  :foo/bdec #f 0}}
This is of course just an example, the real data is from postgresql table. All the casting or remapping to make resultset transit friendly makes code ugly. And it is far from it just works.

tony.kay 2024-10-03T15:37:24.648859Z

Fulcro inspect is a chrome plugin. What you see there is a side-effect of display, not of real type in transit. BigI and BigD definitely work on the wire…so I think you’re just confusing yourself. The Instant support you want is just to install your own additional type handler in Fulcro’s https://book.fulcrologic.com/#_custom_type_support. You’ll encode that with a new namespaced tag you invent, and whatever data you need (e.g. ms epoch time or whatever). Inspect will show the tag and raw data, but the front/back end will work with the new type.

janezj 2024-10-03T15:41:05.907809Z

I just figured out for Instant -> #inst:

(def writer (transit/writer out :json 
  {:handlers {java.time.Instant 
      (transit/write-handler "m" #(-> % .toEpochMilli Long/toString) )}}))

janezj 2024-10-03T15:42:10.712069Z

I just have to insert it into fulcro.

janezj 2024-10-03T15:43:10.077249Z

but f is not deserialzed in frontend. bacause it is report rendered as [TaggedValue: f, 32592165.00]

tony.kay 2024-10-03T15:43:59.083569Z

read my response, and the book

janezj 2024-10-03T16:10:05.848899Z

I think that I understand for Instant, it works by the book, I just reused m.

(fulcro-transit/install-type-handler!
 {:writer {java.time.Instant (transit/write-handler "m" #(-> %
                                                             .toEpochMilli
                                                             Long/toString))}
  :reader {}})
I am confused about BigD which is not decoded on client.

tony.kay 2024-10-03T16:11:29.146659Z

RAD has a numeric ns for using Big.js to implement BigDecimal on the client.

tony.kay 2024-10-03T16:12:38.223479Z

Transit jsut sends a tagged value, but if you want to actually use it, you need to support it like that

tony.kay 2024-10-03T16:12:50.286669Z

because js has no BigD or BigI data type.

tony.kay 2024-10-03T16:14:23.548199Z

All Fulcro guarantees is you’ll get the data transmitted in a way that if Fulcro were to send it back, you’d get a correct round trip. If you want to manipulate the data, then you have to make sure you have functions that can correctly do so, while keeping it in a format that transit can understand.

janezj 2024-10-03T16:39:07.157009Z

so clj backend will write "f" tagged when BigDecimal, but I have to install own reader in cljs to display it as number. com.fulcrologic.rad.type-support.decimal/numeric is support lib? Currently I am solving render with column-formatter, but I don't like it, I would like that it just works.

(defn- cell-fmt-decimal [report-instance ^js value row-props attribute]
  (when value 
    (.-rep value)))
But I can't solve it without formatters, bacause f 22 will be 22M 🙂

tony.kay 2024-10-03T17:48:35.656039Z

Yes, numeric is the support lib.

tony.kay 2024-10-03T17:50:25.788639Z

These are the built-in formatters:

(defn built-in-formatter [type style]
  (get-in
    {:string  {:default (fn [_ value] value)}
     :instant {:default         (fn [_ value] (dt/inst->human-readable-date value))
               :short-timestamp (fn [_ value] (dt/tformat "MMM d, h:mma" value))
               :timestamp       (fn [_ value] (dt/tformat "MMM d, yyyy h:mma" value))
               :date            (fn [_ value] (dt/tformat "MMM d, yyyy" value))
               :month-day       (fn [_ value] (dt/tformat "MMM d" value))
               :time            (fn [_ value] (dt/tformat "h:mma" value))}
     :keyword {:default (fn [_ value _ column-attribute]
                          (if-let [labels (::attr/enumerated-labels column-attribute)]
                            (labels value)
                            (some-> value (name) str/capitalize)))}
     :enum    {:default (fn [_ value _ column-attribute]
                          (if-let [labels (::attr/enumerated-labels column-attribute)]
                            (labels value) (str value)))}
     :int     {:default (fn [_ value] (str value))}
     :decimal {:default    (fn [_ value] (math/numeric->str value))
               :currency   (fn [_ value] (math/numeric->str (math/round value 2)))
               :percentage (fn [_ value] (math/numeric->percent-str value))
               :USD        (fn [_ value] (math/numeric->currency-str value))}
     :boolean {:default (fn [_ value] (if value (tr "true") (tr "false")))}}
    [type style]))

tony.kay 2024-10-03T17:50:33.316699Z

(in RAD report.cljc)

tony.kay 2024-10-03T17:50:51.325739Z

if you’re using RAD. If you are NOT using RAD, then look at those for examples

janezj 2024-10-03T18:10:05.682149Z

I see, wow! there is also install-formatter! Really great. I think that I understand how you designed the RAD. Instead of hacking transit and risk to corrupt the data, you have created an extensible rendering based on attributes. This is the reason why you are encouraging custom types in transit not coercing as I did with Instant. I got a gut feeling that I am doing something fishy. I am again very impressed.

tony.kay 2024-10-03T18:28:15.888659Z

Great, yeah. I figured you were missing something. In my own systems, I've got things installed so that I can use cljc Java time on The wire and in reports or forms. That way I can use local date, zoned date time, etc

janezj 2024-10-03T18:41:15.086209Z

Your system must be another layer of wonders.