Fork me on GitHub
#clojurescript
<
2023-03-02
>
Jakub Šťastný14:03:41

Hey guys. I'm unclear on how to do runtime fns validations in cljs.spec.alpha? I have the example fn ranged-rand from the Spec guide https://clojure.org/guides/spec:

(defn ranged-rand [start end] (+ start (long (rand (- end start)))))
And its validation:
(s/fdef ranged-rand
:args (s/and (s/cat :start int? :end int?)
               #(< (:start %) (:end %)))
  :ret int?
  :fn (s/and #(>= (:ret %) (-> % :args :start))
             #(< (:ret %) (-> % :args :end))))
It works just fine when I do (ranged-rand 0) getting an error as it should. HOWEVER I'm exporting a JS library and I want it to do the validations when called from JS as well:
import { rangedRand } from "./main.js"

rangedRand(0)
This code does NOT fail as I'd like it to, the validations don't run. How do I make CLJS spec to validate on runtime?

Jakub Šťastný14:03:21

In case it's relevant, I use up to date ShadowCLJS with :target :esm.

p-himik14:03:09

Somewhere, something calls cljs.spec.test.alpha/instrument to instrument all the functions for which fdef was called. By itself, fdef doesn't validate anything, it just creates a spec. So I assume that you see the difference in behavior not in the CLJS vs JS scenario but rather in the development build vs production build scenario. In this case , it's very likely that something calls instrument only during the development build.

Jakub Šťastný14:03:59

Hey @U2FRKM4TW. The difference is between compile time (CLJS code) vs. loading that compiled (JS) code in Deno.

Jakub Šťastný14:03:10

What you say about instrument makes sense.

Jakub Šťastný14:03:03

I wonder what's the recommended way to do the instrumentation? One way would be hooking :pre and :post, but I'm not sure whether that's a good pattern(?)

p-himik14:03:10

Do you get errors with (let [x 0] (ranged-rand x))? :pre and :post are ignored in release builds because they use assert.

Jakub Šťastný14:03:31

Yes, I do get an error there (on compile).

Jakub Šťastný14:03:11

Ah, good to know about ignoring :pre:/`:post`.

Jakub Šťastný14:03:49

So then essentially I have to call (s/valid? x) manually in the fn definitions?

p-himik14:03:55

Welp, I have no idea. I just tried it with a (mostly) blank slate project with shadow-cljs. Just plain instrument + fdef is not enough to trigger any error during compilation. Are you sure you're seeing errors from spec and not warnings from compiler type/arity checker? And instrument + fdef is enough for me to get errors in run time. Even when calling an exported function from JS. (tested only development though)

p-himik14:03:23

(defn ^:export my-fn [arg]
  (println arg)
  1)

(s/fdef my-fn
        :args (s/coll-of string?)
        :ret integer?)

(st/instrument)

Jakub Šťastný14:03:59

Oh it's actually a warning, you're right.

Jakub Šťastný14:03:28

@U2FRKM4TW by the way the :export thing, is it still a thing? I've seen it around, but haven't found it mentioned with :target :esm which I'm using, I suppose it's only :target :nodexxx thing? Looks handy for debug.

p-himik14:03:58

No clue about :esm, I only use :browser. @U05224H0W should know.

Jakub Šťastný14:03:53

@U2FRKM4TW OK, made it work with instrument. Thanks you 🙂

👍 2
kennytilton15:03:09

Getting a warning building my web/mx quickstart in a fresh location (my http://github.io repo):

Compile Warning: parse-double already refers to: cljs.core/parse-double being replaced by: no.en.core/parse-double  resources/public/cljs-out/dev/no/en/core.cljc   line:136  column:1
I see https://github.com/r0man/noencore recently adjusted to clj 1.11.0 supplying that, but I do not know which of my dependencies is hitting the old version. I myself do not have a direct dependency on noencore. Starting to check them all now, but...this is a lein project. Anyone know how I can find out who is using noencore? Thx!

p-himik15:03:35

This is really more of a #C0AB48493 question since it's the thing that manages your dependencies. There should be a subcommand to output the full dependency tree (note that you should provide it with the same aliases you used when that warning showed up).

p-himik15:03:39

Ah, lein with-profile +profile1,+profile2 deps :tree.

👀 2
kennytilton15:03:33

Cool, that works. Thx. I had also found:

$ lein pom
$ mvn dependency:tree -Dverbose=true 
That showed me the same author's cljs-http 0.1.46 was using the old version of noencore. Unfortunatey 0.1.47 is still -SNAPSHOT and not deployed. Thankfully the PR has a helpful note:
I have fixed this issue. see #137

If the pull request has not been merged for a long time, you can try to use [io.github.ruffnext/cljs-http "0.1.47"]
That worked! 🙏 "Mama don't let your babies grow up to be programmers."

p-himik18:03:20

FWIW, I wouldn't use a third-party fork of unknown origin just because it's released. I'd rather seek a replacement for cljs-http (interop with JS is both easy and simple, and there's also cljs-ajax). Or, if you really need cljs-http, then I'd vendor it in, assuming its license allows you to do so.

kennytilton19:03:06

Hmm, I used goog.net.Xhrio in my JS whos hiring project, might be a good idea. Thx! 🙏

p-himik20:03:44

Unless you really need that API, I'd use the things that are built into your browser. js/fetch has been around forever (in terms of JS) and all relatively modern browsers support it.

kennytilton20:03:16

Hmmm, ChatGPT offers:

(ns my-namespace
  (:require [cljs.core.async :refer [<!]]
            [cljs.js :as js]
            [cljsjs.fetch]))

(defn fetch-get [url]
  (let [promise (js/Promise. (fn [resolve reject]
                              (let [headers (js-obj "Content-Type" "application/json")]
                                (js/fetch url headers)
                                (.then js/* this
                                       (fn [response]
                                         (when (.ok response)
                                           (resolve (.json response))))))
                              (fn [error] (reject error))))]
    (<! (js/await promise))))
Looks fishy.

p-himik20:03:59

It is completely wrong. I would not waste time with ChatGPT.

kennytilton23:03:07

Yeah, had a feeling. It just occurred to me that, the way things are turning out, I can pull XHR out of Web/MX altogether. Let clients decide what to use. I'll take the easy way out in a separate examples replo, go with cljs-ajax.

kennytilton18:03:49

Cool. Except for the neato digital LED font, the Web/MX quickstart doc is now an app, grace a Github Pages: https://kennytilton.github.io/web-mx-quickstart/ • comments have been added to the source; and • a "glossary" button toggles the display of the dozen MX functions needed. I think I want to simplify the navigation API, and the cell formula variants, so I can get the w/mx API down to seven. If that was enough for McCarthy, it is enough for me. Right now I am at a dozen. Comments/requests welcome!

Jakub Šťastný21:03:25

Hey. Has anyone seen these: Could not set npm package requirements. Error getting response at for package "shadow-cljs": An npm specifier not found in cache: "shadow-cljs", --cached-only is specified.? (Details in the thread.)

Jakub Šťastný21:03:27

I have a project on the latest shadow-cljs with :target :esm and I'm getting this code within deno repl when I load the generated code into it.;

Jakub Šťastný21:03:52

It's rather annoying, I'm hoping to get rid off it, but I'm not understanding where is it coming from.

p-himik21:03:39

There's also #C6N245JGG

👍 2
Jakub Šťastný21:03:02

Right good point.

vincent23:03:45

preferred way to connect Stripe in cljs? a survey x)

p-himik20:03:14

Never had to use Stripe but would not look past https://stripe.com/docs/js