Fork me on GitHub
#clojurescript
<
2020-05-05
>
Jakob Durstberger07:05:32

I am trying to convert some javascript into clojurescript and I am not sure if I am doing it right. I don’t get any errors but I think I might be doing something wrong. I am trying to convert the following as can be found here: https://docs.amplify.aws/lib/auth/start/q/platform/js#re-use-existing-authentication-resource

import Amplify, { Auth } from 'aws-amplify';

Amplify.configure({
    Auth: {
        region: 'XX-XXXX-X',
        userPoolId: 'XX-XXXX-X_abcd1234',
        userPoolWebClientId: 'a1b2c3d4e5f6g7h8i9j0k1l2m3',
    }
});

// You can get the current config object
const currentConfig = Auth.configure();
I got:
(defn configure []
  (.configure
    Amplify
    (clj->js {Auth {:region "eu-west-1"
                    :userPoolId "eu-west-1_xxxxxxx"
                    :userPoolWebClientId "xxxxxxxxxxxxx"}}))
  (.configure Auth))
Is thar correct? Thanks 🙂

Roman Liutikov07:05:27

you could create js objects directly

#js {:Auth #js {:region ...}}

Roman Liutikov07:05:07

in your example above Auth should be :Auth

Jakob Durstberger07:05:09

Oh nice, I wasn’t aware of #js, thank you

Setzer2208:05:25

hi! Is there a way I could integrate something like this into my re-frame application? https://github.com/elrumordelaluz/reactour This is the code I'd need to "translate":

import React from 'react'
import Tour from 'reactour'

class App extends Component {
  // ...

  render  (
    <>
      { /* other stuff */}
      <Tour
        steps={steps}
        isOpen={this.state.isTourOpen}
        onRequestClose={this.closeTour} />
    </>
  )
}

const steps = [
  {
    selector: '.first-step',
    content: 'This is my first Step',
  },
  // ...
]

victorb09:05:03

yeah, I don't see any immediate reason why not. Did you give it a try and getting errors? Only cumbersome part is getting npm dependencies to work correctly, but there is bunch of guides online on how to get that to work, depends on what build tool you're using too

Setzer2210:05:36

Yes, my main concern was how to translate the "imports" and how to declare the library as a dependency. The solution to the first one I found it here: https://clojureverse.org/t/guide-on-how-to-use-import-npm-modules-packages-in-clojurescript/2298 And in shadow-cljs, importing the library as a dependency was as simple as npm install in my project folder 😅

Setzer2210:05:16

But all this was more difficult to find that I expected, given the wide availability of React components and how easy everything really was in the end...

Setzer2210:05:20

(for any curious readers) I also used this as a reference: https://www.rockyourcode.com/how-to-build-a-markdown-preview-app-with-reagent/

👍 8
David Pham14:05:22

congratulations 🙂

frozenlock22:05:38

I'm trying to get a hold of a map from a parent window ( js/window.opener ). Everything looks fine, except that something weird is happening with the keys:

;; Define the map in the parent window
(when-not js/window.opener
  (def test-map {:a 1}))

;; In the child window, try to get a hold of the map
(when-let [opener js/window.opener]
  (when (not= js/window opener)
    (prn (assoc (into {} (js-get-in js/window.opener ["mynamespace" "test_map"]))
                :a 2))))

{:a 1, :a 2}
I find myself with two (2) :a keys. Bug? Feature? I'm doing everything wrong? 😛

frozenlock22:05:32

Oh, and the into is necessary, otherwise all I see when printing the map is #object[Function]

lilactown22:05:54

you’ve loaded this CLJS code in a separate window?

noisesmith22:05:29

try checking the types of the keys - maybe they both print as :a but aren't equal?

frozenlock22:05:46

Both are of type 'cljs.core/Keyword`, but they aren't equal.

noisesmith22:05:19

aha - as an optimization clojure does identity equality for keywords (and attempts to ensure only one of each keyword ever exists) - but by loading cljs twice you can get two of a keyword that aren't equal

noisesmith22:05:28

I think I understand now

lilactown22:05:30

each window is it’s own JS “realm” or context - you cannot share data structures between the two

frozenlock22:05:31

Yes; I have small application opening a child window opening the same cljs code.

lilactown22:05:23

each window will have it’s own version of keyword, map, etc. and they won’t be compatible

4
lilactown22:05:32

IIRC, anyway

lilactown22:05:27

like, you have a separate script tag in this window right? that loads all of cljs.core?

frozenlock22:05:39

But I'm pretty sure I can share variables between parent/child windows. As for complex datastructure, I don't know.

frozenlock22:05:40

I can print the list of keys in a map, but they are never equal from one window to the next. 😕

lilactown22:05:13

yeah, each window has it’s own version of cljs.core, so they won’t be equal

frozenlock22:05:18

Hmm... then I wonder if I can simply copy the context from the parent to the child. I'm gonna give it a try.

lilactown22:05:17

I think your best bet is to serialize the structures between the two

noisesmith22:05:04

I bet you could even fix it by walking the hash-map and calling keyword on every keyword

lilactown22:05:09

this isn’t just a CLJS problem, it’s a JS thing: https://stackoverflow.com/a/49832343/4379329

😞 4
frozenlock22:05:10

Yes there are multiple approaches to share serialized data, but unfortunately I have many identical MBs of data to share.

Chris McCormick03:05:11

the way i have solved this recently is putting the data into localStorage or indexDB and using window.postMessage to trigger read/write of the share datastore. a cool thing about localStorage which you may not know is that it emits and event in every window from the same domain. So if you have two tabs open for the same site you can use localStorage to write data and also communicate that data has been written. Good luck!

💡 4
Chris McCormick03:05:40

Of course this won't work for rich clojure types, but you can serialize to EDN or JSON or similar.

noisesmith22:05:19

since the equality / return of keyword is based on interning

noisesmith22:05:02

this doesn't come up for non-interned types (symbols, strings, hash maps) as they use value equality

lilactown22:05:55

I’m surprised that you can even use any data structures shared between the two windows. you’re pretty much relying on undefined behavior

noisesmith22:05:08

(though you might need something fancier than calling keyword, as that function might short circuit if the type is already keyword, and not catch that it isn't the interned one)

noisesmith22:05:48

@lilactown it makes sense that it would work - it's two of the same cljs version, so the bytes have identical meaning, until you hit something that's not a value type (keywords)

lilactown22:05:17

it doesn’t work like that

lilactown22:05:01

lots of things rely on constructor or reference identity, which you don’t share between the two windows

lilactown22:05:20

it’s hard to know what will work and what will not without understanding the internals of cljs.core

noisesmith22:05:31

OK -fair enough

noisesmith22:05:45

of the "vanilla" data types - the things that work in edn without reader tags - I would expect keywords to be the gotcha, but then again it should be easy to verify what does or doesn't work for a given browser engine

lilactown22:05:36

sharing large amounts of data between windows is currently not a greatly supported thing

4
Chris McCormick03:05:11

the way i have solved this recently is putting the data into localStorage or indexDB and using window.postMessage to trigger read/write of the share datastore. a cool thing about localStorage which you may not know is that it emits and event in every window from the same domain. So if you have two tabs open for the same site you can use localStorage to write data and also communicate that data has been written. Good luck!

💡 4