Fork me on GitHub
Bardia Pourvakil03:03:21

Anyone have any idea why I’m not able to access my namespaces in my CIDER nrepl session into my shadow-cljs project


defmethod ends up as a deftype with a method table as an atom. Is it gross to (keys @(.-method-table my-method)) ?


if i want to know the args for which there is a defmethod


isn't that methods?


wow thanks! didn't know about that one

👍 4
Vishal Gautam16:03:45

has anyone used reitit routing library on the frontend


Hi guys, what's the best way to handle stripe payments in the client side in a re-agent app?


Like here,, there's a way to put a script tag in the html


and then do

var stripe = Stripe('pk_test_sadljfdslafjsdalfjsdljfkjls');
var elements = stripe.elements();
in js. How to replicate this in clojurescript? When I do (.. Stripe 'pk_test_sadljfdslafjsdalfjsdljfkjls'), I get that Stripe isn't defined.

Michaël Salihi16:03:11

You can try: (Stripe. "pk_test_sadljfdslafjsdalfjsdljfkjls")

Michaël Salihi16:03:59

How do you require Stripe ?


I just add a script tag in my index.html


(Stripe. "sdfasfdsaashqerhq") doesn't work


it says undeclared variable Stripe.


@pshar10 what compiler are you using?


you’ll need to configure externs for stripe


How do I do that?


“Undeclared variable” sounds like it isn’t loading the js for Stripe at all, maybe you need to include a <script> tag in your enclosing HTML document? Or possibly use shadow-cljs.


there are many ways. you can try using cljsjs: which involves adding a dependency in your deps.edn to cljsjs/stripe and then requiring it like:

[stripe :refer [Stripe]]
(I think that’s the right require, not sure)


I don't know how to add a dependency in a deps.edn. I don't have that file in my project


FWIW, referring to global JS variables requires you to add js/ at the beginning of the symbol. js/window, js/document, etc. but in this case, it’s better to have the externs since it will help prevent errors when doing advanced optimizations


@pshar10 are you using leiningen? it would be project.clj then


@lilactown I required it like so in my project.clj [cljsjs/stripe "3.0-0"]. I get "No such namespace: stripe, could not locate stripe.cljs, stripe.cljc, or JavaScript source providing "stripe"", where I used it [stripe :refer [Stripe]]


did you restart your compiler too?

👍 4

I’m not sure about the require, it’s hard to tell from cljsjs what the correct namespace is for externs


I have a general question. How to import any js library in a clojurescript project (Figwheel) without using cljsjs? Like is there something as simple as doing npm install --save whatever?


i think this is where shadow-cljs shines and actually fulfill's Clojure's promise of easy interop with the host language ecosystem


how reliable is "externs inference" ? does it requires manual intervention occasionally?


I use shadow-cljs’ externs inference and it’s pretty good


oh there are two competing impletations


I'm okay with using js/Stripe which works. However, I have a problem with js promises: I'm trying to convert this js code:

stripe.createToken(card).then(function(result) {
    if (result.error) {
      // Inform the customer that there was an error.
      var errorElement = document.getElementById('card-errors');
      errorElement.textContent = result.error.message;
    } else {
      // Send the token to your server.
And I have the following:
     (let [result (<!
                   (.createToken stripe @(subscribe [:card-element]))
       (prn "result is" result)
       ;; (if (.-error result)
       ;;   (.textContent (js/document.getElementById "card-errors") (.-message .-error result))
       ;;   (prn "response is" (js/stripeTokenHandler (.-token result)))
       ;;   )
But I get the error:


No protocol method ReadPort.take! defined for type object: [object Promise]


you're calling <! on a promise. .createToken returns a promise not a channel that you can take from


I was conflating these concepts. How do I do the javascitip .then() part in cljs?


(.then promise callback).


Is it possible to make a ratio or bigdec type as a library in cljs that plays nice with the rest of the number system (ie all arithmetic and comparisons work with regular numbers)?


Only if you use some custom functions instead of the built-in ones like +, -, and so on, and use them everywhere. Which means that this approach doesn't really scale beyond your own application code.

eccentric J19:03:22

Thought this would make for a convenient macro for this small side project. Howerver I can't get it to work. I get an Can't use qualified name as parameter error due to resolve and reject being qualified in the ns.

(defmacro promise

  (promise (resolve 5))
  (promise (reject  (js/Error. \"oops\")))
  `(js/Promise. (fn [resolve reject] ~body)))


Are resolve and reject functions or just indicators that the promise is being resolved/rejected?

eccentric J19:03:51

Pretty sure resolve and reject are functions

eccentric J19:03:16

The equivalent JS of the first example:

new Promise(function (resolve, reject) { 


Wouldn’t you want (fn [resolve & reject] ~body) since you wouldn’t be resolving and rejecting a the same time? (acknowledging this is unrelated to your original question)

eccentric J19:03:18

The default JS Promise constructor always provides a resolve and reject args to the function.


I see, thanks.

eccentric J19:03:46

(println (macroexpand '(p/promise
                        (resolve 5))))

;; =>

(new js/Promise
     (cljs.core/fn [cljs.core/resolve project.promise/reject]
       (resolve 5)))


you need to quote those anaphoric symbols i believe


sorry you want ~'

eccentric J20:03:30

Thanks! Just found the same solution recommended in clojuredocs defmacro examples

(defmacro promise

  (promise (resolve 5))
  (promise (reject  (js/Error. \"oops\")))
  `(js/Promise. (fn [~'resolve ~'reject] ~body)))

parens 4
Ben Hammond21:03:17

what is the state-of-the-art idiomatic way to work with JS Promises? (somehow) convert them into core.async Promise Channels? [funcool/promesa "4.0.0"] ? Plain ol' interop?

Chris O’Donnell21:03:57

I like to convert them to core async channels using

👍 4
Ben Hammond21:03:45

thanks will look at that


I wouldn’t use core.async just for promises. most of my apps haven’t used core.async so I just use interop


if your app already uses core.async, then wsscode-async seems nice

Chris O’Donnell21:03:48

I agree that interop is fine if you're not using core async elsewhere in the app 👍

Ben Hammond21:03:04

ooh yeah that looks pretty fluent

Ben Hammond21:03:11

thats very helpful

Ben Hammond21:03:08

I am using core.async anyway, for websocket comms

eccentric J22:03:00

Started drafting some macros over the weekend to smooth out interop a bit for a project using cljs + puppeteer. Came up with these, which may not be quite as helpful for your project but I'm interested in feedback if anything here is useful or if it only mirrors someone elese's work.

👍 4
Jacob O'Bryant17:03:44

I use a macro that converts promises to channels, e.g.:

(go (prn (js<! (some-promise))))

eccentric J00:04:23

Wow that's really slick! I was thinking about how to make a macro like p/let and p/try but athos clearly beat me to it 😄


I just use interop

👍 4
Mario C.23:03:23

I need to give certain input elements a datamask depending on the type of class it has. I am using Reagent and I am wondering how could I do this if I am using this Is there a way to apply this while creating the input component? Currently the way it is being done is calling (-> (js/jQuery ".hasDatePicker") (.inputmask "99/99/9999" (clj->js {:clearIncomplete true}))) on :component-did-update which is on a component that wraps a whole form element, that contains all the inputs. This doesn't seem to be the proper way of doing it.