Fork me on GitHub
#clojurescript
<
2021-09-27
>
zendevil.eth10:09:46

I have a production and a development environment, but I don’t understand this: This is my code:

(let [provider
          (new (.. ethers -providers -Web3Provider)
               (.-ethereum js/window) "any")
          _ (js/console.log "provider is " provider)
          contract (try 
                     (new (.. ethers -Contract)
                          address
                          (.-abi (js/JSON.parse contract-json))
                          provider)
                     (catch js/Object e (prn "error:" e)))
          _ (js/console.log "contract is " contract)
          amount (try (<p! (.. contract (totalAmountRaised)))
                      (catch js/Object e (prn "error:" e)))]
        (prn "amount is " amount)
        (dispatch [:set-total-amount-raised amount]))
In development it works file and I see the prn “amount is ” #object[BigNumber 107250000000000000]. But when I deploy this on google cloud gke, I see the following for the same code: The exception is catched:
"error:" #object[TypeError TypeError: p.ql is not a function]
and “amount is ” nil

zendevil.eth10:09:19

and looking at the app.js code for p.ql doesn’t really do me any good

p-himik10:09:17

Your production code is minimized. When you use JS interop, you gotta know which fields can and cannot be renamed. Those should correspond 1-to-1 to the fields that should and should not be renamed. Externs help with that. There are multiple resources on externs, but these two should give you what you need: • https://clojurescript.org/guides/externshttps://code.thheller.com/blog/shadow-cljs/2017/11/06/improved-externs-inference.html

zendevil.eth10:09:51

so I added ^js tags on provider and contract, but I still see the warning

zendevil.eth10:09:04

Cannot infer target type in expression (. inst_61399 (totalAmountRaised))

zendevil.eth10:09:39

This is what I have now:

[provider
          ^js (new (.. ethers -providers -Web3Provider)
                   (.-ethereum js/window) "any")
          _ (js/console.log "provider is " provider)
          contract ^js (try 
                         (new (.. ethers -Contract)
                              address
                              (.-abi (js/JSON.parse contract-json))
                              provider)
                         (catch js/Object e (prn "error:" e)))
          _ (js/console.log "contract is " contract)
          amount (try (<p! (.. contract (^js totalAmountRaised)))
                      (catch js/Object e (prn "error:" e)))]

p-himik10:09:50

You have to add ^js in front of every expression which type cannot be inferred. I assume in this case it's inst_61399. If you have forms like .., then I think you have to add ^js in between the forms. If you still can't figure it out with all that in mind, just split all JS field accesses and function calls into separate unchained expressions, and see which are missing ^js.

zendevil.eth10:09:21

inst_613199 is contract, and there’s already a ^js there

zendevil.eth10:09:52

also I’ve heard that ^js doesn’t work so well inside go

zendevil.eth10:09:02

that might be the cause

p-himik10:09:05

Also, add ^js to the symbol and not to the form that you assign to the symbol. So it should be ^js contract (...). I think both work, but this is proper and makes you think in the right plane.

p-himik10:09:35

^js does not work inside go at all. You can extract all functionality that uses ^js in a separate function and use that function within go - it'll work.

lilactown16:09:15

yeah, there is a bug in go forms

lilactown16:09:52

if you don't want to mess with externs, you can also use goog.object functions

maverick10:09:37

How can I setDatasource in clojurescript using javascript interlop onGridReady = params => {     this.gridApi = params.api;     this.gridColumnApi = params.columnApi;     const httpRequest = new XMLHttpRequest();     const updateData = data => {       var dataSource = {         rowCount: null,         getRows: function(params) {           console.log("asking for " + params.startRow + " to " + params.endRow);           setTimeout(function() {             var rowsThisPage = data.slice(params.startRow, params.endRow);             var lastRow = -1;             if (data.length <= params.endRow) {               lastRow = data.length;             }             params.successCallback(rowsThisPage, lastRow);           }, 500);         }       };       params.api.setDatasource(dataSource);     };

p-himik10:09:07

It will be easier to answer your question if you use proper code block formatting. Also, there are many resources on JS interop - guides, examples, cheatsheets, etc. What have you tried so far?

maverick10:09:00

onGridReady = params => {
    this.gridApi = params.api;
    this.gridColumnApi = params.columnApi;

    const httpRequest = new XMLHttpRequest();
    const updateData = data => {
      var dataSource = {
        rowCount: null,
        getRows: function(params) {
          console.log("asking for " + params.startRow + " to " + params.endRow);
          setTimeout(function() {
            var rowsThisPage = data.slice(params.startRow, params.endRow);
            var lastRow = -1;
            if (data.length <= params.endRow) {
              lastRow = data.length;
            }
            params.successCallback(rowsThisPage, lastRow);
          }, 500);
        }
      };
      params.api.setDatasource(dataSource);
    };

    httpRequest.open(
      "GET",
      ""
    );
    httpRequest.send();
    httpRequest.onreadystatechange = () => {
      if (httpRequest.readyState === 4 && httpRequest.status === 200) {
        updateData(JSON.parse(httpRequest.responseText));
      }
    };
  };

maverick10:09:39

I am trying to implement ag-grid infinite scrolling in clojurescript

maverick10:09:35

I am trying to implement onGridReady and in console when I print params I get this {:type gridReady, :api #object[a [object Object]], :columnApi #object[a [object Object]]}

p-himik10:09:58

So what's the problem? In JS, params.api gets the value of the field api from the object referenced by params. In CLJS, (:api params) gets the value of the key :api from the map referenced by params.

maverick10:09:59

the setDatasource in not found

p-himik10:09:57

I'll repeat myself: > What have you tried so far?

p-himik10:09:04

You haven't provided any CLJS code.

maverick12:09:39

(defn set-datasource [params data]
      (let [paramsData (js->clj params :keywordize-keys true)]
           (println (js->clj (get-in paramsData [:api :setDatasource]) :keywordize-keys true))
           (swap! paramsData update-in [:api :setDatasource] { "getRows" (fn [event]
                                                                             (println event)
                                                                             (let [eventData  (js->clj event :keywordize-keys true)
                                                                                   endRow (get-in eventData [:endRow])
                                                                                   startRow (get-in eventData [:startRow])

                                                                                   ]
                                                                                  (println (str "startrow" startRow))
                                                                                  (println (str "edrow" endRow)))
                                                                             )

                                                              })))

maverick12:09:48

this is what i have implemented

p-himik12:09:01

If it works then good, but you don't need to use js->clj - you can just use JS interop. It's more direct, less error-prone, and more efficient because there will be no data conversion.

maverick12:09:27

"onGridReady" (fn [params]
(let [data  (get-data)]                                            (.. js/params -api setDatasource { "getRows" (fn [event]                                                                                             (println event)                                                                                            (let [eventData  (js->clj event :keywordize-keys true)                                                                                     endRow (get-in eventData [:endRow])                                                                                         startRow (get-in eventData [:startRow])                                                                                                   ]                                                           (println (str "startrow" startRow))                                                                                                 (println (str "edrow" endRow)))                                                          )})))

maverick12:09:34

Will this work ?

p-himik13:09:28

No clue, because: • There are many more factors outside of this tiny snippet of code • Your didn't put any effort in formatting the code, so it's completely unreadable

maverick13:09:50

I am using onGridReady in grid options

maverick13:09:35

first i am getting data from API and then trying to setDatasource for (fn [params] ) like

maverick13:09:20

(.. js/params -api setDatasource { "getRows" (fn [event]) })

p-himik13:09:32

js/params takes the value of a global JS variable named param. You need just param since that's what you pass into your onGridReady function. setDatasource, being a JS function, probably expects a JS object as its argument, but you're passing a CLJS map. Add #js in front of that opening { .

maverick13:09:42

okay, am I calling it right because I am getting error as Caused by: java.lang.Error: Unknown dot form of (. (. (. params -api) setDatasource) #object[cljs.tagged_literals.JSValue 0x6422aaf6 "cljs.tagged_literals.JSValue@6422aaf6"] nil)

p-himik13:09:03

Ah, right - wrap setDatasource and its argument in ().

maverick13:09:02

used it I am getting Uncaught TypeError: Cannot read property 'setDatasource' of undefined

p-himik13:09:50

What's your CLJS code right now?

maverick14:09:12

(.. params -api (setDatasource #js {:getRows   (fn [event]                                                             (println event)                                                                                                                     )}))

maverick14:09:48

do i need to include ^js

maverick14:09:02

I am trying to replicate params.api.setDatasource

p-himik14:09:46

^js is necessary for the right externs inference during the production build, so that api or setDatasource names are not mangled. It's not needed in development, but won't hurt.

maverick14:09:43

It is still not working

maverick14:09:07

Do I need to use goog.object/getValueByKeys to get api first and than user setDatasource ?

maverick15:09:55

@U2FRKM4TW This worked

(.setDatasource (goog.object/getValueByKeys params #js ["api"])  (clj->js {:getRows (fn [event])}))

p-himik16:09:55

That's exactly what ^js is for. Could be rewritten as

(.. ^js params -api (setDatasource #js {:getRows (fn [event])}))
You might need to add an extra ^js in there if that doesn't work in production due to setDatasource being renamed.

maverick16:09:11

okay let me try this too. Thanks

p-himik16:09:42

Just tested - one ^js is enough. And ideally, it should be added right where you bind the value to a new name, to the function signature should be [^js params] instead of just [params] - then any access to the fields within params, even nested ones, should work just fine in production.

maverick07:09:16

I am getting error when calling successCallback as it is not a function

maverick07:09:58

Uncaught TypeError: a.Zf is not a function
    at Object.getRows (VM38 admin.js:2783)

p-himik08:09:38

Yet again - you're missing ^js somewhere. Read about externs. These are good resources: • https://clojurescript.org/guides/externshttps://code.thheller.com/blog/shadow-cljs/2017/11/06/improved-externs-inference.html

maverick08:09:49

(.successCallback ^js params (clj->js (get-in data-json [:data])) (clj->js (get-in params [:endRow])))
I am calling like this

p-himik08:09:59

That's just one line from your code. I don't know what makes you sure that it's the line that causes the problem. I have provided you with everything I knew that's relevant to the topic, including the links for further reading. The rest is up to you.

ccann21:09:18

I’m trying to enable source maps in combination with using webpack to bundle the code. Anyone have experience doing this? Our builds work but I don’t know how to get webpack to incorporate the source map main.js.map that cljsbuild creates.

ccann21:09:20

webpack wants to generate its own source maps and I think all I want it to do is copy the existing source map file to our host and ensure its named correctly