clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
souenzzo 2021-06-05T03:25:48.021900Z

Hello My team needs to deliver a nodejs library to another team The other team expect a typescript-like user experience: a beautiful docs website and maybe an autocomplete. Which tools I can use from cljs world to do that? Like, I can generate docs via JSDocs or some other tool that document the API for javascript users, not for clojure users.

dazld 2021-06-05T16:58:54.056600Z

Did you figure this out? An option could be to emit JSDoc comments around your exported functions. Typescript will pick up those annotations.

dazld 2021-06-05T16:59:37.057400Z

Probably your TS api docs would work then too.

dazld 2021-06-05T17:01:03.057700Z

https://cljs.github.io/api/cljs.core/js-comment

dazld 2021-06-05T17:01:20.058100Z

Pretty sure that would work.

dazld 2021-06-05T17:02:33.059600Z

Little known fact about TS is that it falls back to jsdoc in some situations, and buried inside it is an implementation of supporting types via jsdoc comments.

dazld 2021-06-05T17:04:22.060600Z

Guess this was on your radar already though

souenzzo 2021-06-05T18:34:23.060800Z

very valuable all this information As a clj dev I doent even know how to start to search things like "how do typescript do autocomplete" thank you so much @dazld, I will try to do some POC and maybe a blog post about it šŸ™‚

šŸ‘ 1
dazld 2021-06-05T18:35:26.062100Z

Iā€™m interested in this topic too - if you remember me when you have something concrete, please do ping

dazld 2021-06-05T18:37:12.063300Z

It might even be that you can skip TS completely and just ship jsdoc comments.. perhaps.

dazld 2021-06-05T18:39:18.064500Z

Some macro magic may be appropriate, translating specs into jsdoc..

dazld 2021-06-05T18:39:47.065100Z

Interesting question, thanks for asking.

šŸ‘ 1
2021-06-05T14:34:34.038400Z

What is the best practice to compile some EDN data in .clj file, for consumption in .cljs files? Considering .cljc file, but I only need the .clj code at compile time. I am trying to use a https://github.com/shegeley/airtable-clj to download my data, then use shadow-cljs to compile a web-site with live-reload. I am using https://github.com/OrgPad-com/volcano library, which runs the the web page templating code with shadow-cljs and Reagent cljs when in dev mode, then uses clj via Lein to compile static html for production. It uses .cljc files for this code. It is nice to have a responsive dev mode, but it feels confusing and limiting for me to constrain myself to only code that can be run in both runtimes? I donā€™t want to try to re-duplicate the AirTable download and parsing code, just to run it in cljs runtime. Maybe Iā€™m over-thinking it. Seems like it should be possible to have some clj functions that return data, then depend upon them in proper shadow-cljs build. Hopefully without having to treat them both like alien runtimes: Lein compile the clj to edn, then pre-load that into shadow-cljs as an in-lined resource, or have the cljs use a fetch function to read it as an external resource. Any hints? Thanks

borkdude 2021-06-05T15:10:48.039100Z

@chromalchemy you can do this using a macro

thheller 2021-06-05T15:19:03.040300Z

depending on the total size I would recommend downloading it in CLJS. inlining is fine for really small files, eg via https://clojureverse.org/t/using-none-code-resources-in-cljs-builds/3745

2021-06-05T15:32:02.044500Z

Thanks guys. @thheller I have successfully inlined some data using that method on another project, it worked! And was crucial to that moment :simple_smile:. But wouldnā€™t I still need to run some process to download and save the data first, before shadow-cljs can inline it? How could this be worked into a repeatable shadow-cljs build? @borkdude I will try the macro solution too.

thheller 2021-06-05T15:35:55.045400Z

if it can change over time I would manage that data on the server and have your frontend download it when needed

2021-06-05T16:10:47.047700Z

Ok, I will consider that. I wanted to keep production site relatively static and simple. It doesnā€™t have to change often. I will not be using cljs on the production site. The cljs is only running for live-reload (which is probably over-complicating this whole thing.

2021-06-05T16:15:30.051900Z

@thheller wrote in another post > macros rewrite Clojure code at compilation time. They just take the raw form that was passed into the call and rewrite it to something else. They never eval their arguments. > On top of that the macros for ClojureScript are expanded at compilation time which happens in Clojure on the JVM. So they donā€™t have access to any JS at all. So in my context, would putting the .clj based Airtable data request and parsing code into a macro ā€œmagicallyā€ make it run in .cljs also? Was just hoping it could eval the .clj code as part of the shadow-cljs compile phase, and .cljc files depend on that resulting data.

thheller 2021-06-05T16:17:35.052600Z

it is not clear what you are trying to do here. would help to see some code. sounds like you are making the problem way more complicated that it needs to be.

thheller 2021-06-05T16:18:15.053200Z

"eval the .clj code". using a macro does that, so sounds like you want to write a macro?

2021-06-05T16:56:02.055300Z

Hmm.. Ok Iā€™ll try to sort it out. I wasnā€™t sure if the .clj macro from called from .cljs could eval and return the data. But it seems so. I appreciate your other suggestions though, and will them.

takis_ 2021-06-05T19:19:18.066800Z

Hello I compiled this simple code

(ns tempproject.tempnamespace)(defn ^:export add_cj [n1 n2] (+ n1 n2))
And i got the js file , someone told me that i can access the add_cj by calling tempproject.tempnamespace.add_cj(1,2); for example and it works ,but i give this code to MongoDB and it says ReferenceError: tempproject is not defined

takis_ 2021-06-05T19:22:03.067700Z

on the js that is generated i dont see a var temproject, but code works, i tested it

takis_ 2021-06-05T19:23:09.068600Z

the way of accesing the function with tempproject.tempnamespace.add_cj(1,2); should be working in all js enviroments? can i use something else to access add_cj ?

thheller 2021-06-05T19:24:17.068900Z

how did you compile it?

takis_ 2021-06-05T19:24:38.069100Z

clojure -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version \"1.10.741\"}}}' -m cljs.main -O advanced -c 

thheller 2021-06-05T19:25:57.070200Z

I don't know mongodb but I guess it probably expects some commonjs or ES module format

takis_ 2021-06-05T19:26:34.070800Z

is there an alternative way to acces the exported function?

thheller 2021-06-05T19:27:02.071200Z

do you have a JS example for the mongodb side? what it expects?

takis_ 2021-06-05T19:27:52.071600Z

i use it with java , so i give the code as string

takis_ 2021-06-05T19:28:37.071900Z

function add_cj(arg__0,arg__1) { if(typeof Math.imul == "undefined" || (Math.imul(0xffffffff,5) == 0)) {
    Math.imul = function (a, b) {
        var ah  = (a >>> 16) & 0xffff;
        var al = a & 0xffff;
        var bh  = (b >>> 16) & 0xffff;
        var bl = b & 0xffff;
        // the shift by 0 fixes the sign on the high part
        // the final |0 converts the unsigned value into a signed value
        return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0)|0);
    }
}


            ;var c=this||self;function e(a){var b=a.length;if(0<b){for(var h=Array(b),d=0;d<b;d++)h[d]=a[d];return h}return[]};function f(){this.c=""}f.prototype.toString=function(){return"SafeScript{"+this.c+"}"};f.prototype.a=function(a){this.c=a};(new f).a("");function g(){this.g=""}g.prototype.toString=function(){return"SafeStyle{"+this.g+"}"};g.prototype.a=function(a){this.g=a};(new g).a("");function k(){this.f=""}k.prototype.toString=function(){return"SafeStyleSheet{"+this.f+"}"};k.prototype.a=function(a){this.f=a};(new k).a("");function l(){this.b=""}l.prototype.toString=function(){return"SafeHtml{"+this.b+"}"};l.prototype.a=function(a){this.b=a};(new l).a("\x3c!DOCTYPE html\x3e");(new l).a("");(new l).a("\x3cbr\x3e");var m={},n={};if("undefined"===typeof m||"undefined"===typeof n||"undefined"===typeof p)var p={};if("undefined"===typeof m||"undefined"===typeof n||"undefined"===typeof q)var q=null;if("undefined"===typeof m||"undefined"===typeof n||"undefined"===typeof r)var r=null;if("undefined"===typeof m||"undefined"===typeof n||"undefined"===typeof t)var t=null;if("undefined"!==typeof Symbol){var u=Symbol;"object"!=typeof u||!u||u instanceof Array||u instanceof Object||Object.prototype.toString.call(u)}
var v="undefined"!==typeof Math&&"undefined"!==typeof Math.imul&&0!==Math.imul(4294967295,5)?function(a,b){return Math.imul(a,b)}:function(a,b){var h=a&65535,d=b&65535;return h*d+((a>>>16&65535)*d+h*(b>>>16&65535)<<16>>>0)|0};function w(a){a=v(a|0,-862048943);a=0^(v(a<<15|a>>>-15,461845907)|0);a=(v(a<<13|a>>>-13,5)+-430675100|0)^0;a=v(a^a>>>16,-2048144789);v(a^a>>>13,-1028477387)}w(1);w(0);if("undefined"===typeof m||"undefined"===typeof n||"undefined"===typeof x)var x=null;
"undefined"!==typeof console&&(q=function(){return console.log.apply(console,e(arguments))},r=function(){return console.error.apply(console,e(arguments))});if("undefined"===typeof m||"undefined"===typeof n||"undefined"===typeof y)var y=function(){throw Error("cljs.core/*eval* not bound");};function z(a,b){return a+b}var A=["tempproject","tempnamespace","add_cj"],B=c;A[0]in B||"undefined"==typeof B.execScript||B.execScript("var "+A[0]);for(var C;A.length&&(C=A.shift());)A.length||void 0===z?B=B[C]&&B[C]!==Object.prototype[C]?B[C]:B[C]={}:B[C]=z; return tempproject.tempnamespace.add_cj(arg__0,arg__1); } 


console.log(add_cj(1,2));

takis_ 2021-06-05T19:29:01.072800Z

this is my code , it runs from example in http://playcode.io.

thheller 2021-06-05T19:29:19.073Z

thats irrelevant to my question. I don't know the mongodb parts so I expect that it maybe requires something special to be exported or so

thheller 2021-06-05T19:30:46.074400Z

and this isn't advanced output, so you did some custom wrapping?

takis_ 2021-06-05T19:31:00.074700Z

yes i didnt do anything big

takis_ 2021-06-05T19:31:24.075300Z

only wrap it on function add_cj and in the end i added return tempproject.tempnamespace.add_cj(arg__0,arg__1);

takis_ 2021-06-05T19:31:35.075600Z

to make the code a function

thheller 2021-06-05T19:31:36.075700Z

yeah but why?

takis_ 2021-06-05T19:31:49.076Z

mongodb need 1 function as argument

takis_ 2021-06-05T19:32:01.076300Z

not any js code

thheller 2021-06-05T19:32:11.076500Z

unless you can point me to some mongodb docs or example I really cannot help you

takis_ 2021-06-05T19:32:44.077Z

ok i know , but me accesing the function with tempproject.tempnamespace.add_cj(arg__0,arg__1); is ok?

thheller 2021-06-05T19:32:49.077300Z

no

takis_ 2021-06-05T19:33:30.078200Z

ok do you know how to access it properly? it works this for example in http://playcode.io

thheller 2021-06-05T19:33:47.078700Z

> unless you can point me to some mongodb docs or example I really cannot help you

takis_ 2021-06-05T19:34:07.079100Z

i dont have a place to explain limitations

takis_ 2021-06-05T19:34:18.079300Z

i was searching for that in mongodb

takis_ 2021-06-05T19:34:38.079700Z

but for normal js , how i should acces the exported function ?

takis_ 2021-06-05T19:36:36.080200Z

but this wont help

takis_ 2021-06-05T19:37:27.080500Z

it just says give a javascript function as string

takis_ 2021-06-05T19:39:08.080700Z

it expects this "function(arg1, arg2, ...) { ... }"

thheller 2021-06-05T19:39:58.081200Z

that looks like it'll just serialize the entire code and send it to the server? that'll be tricky with cljs

takis_ 2021-06-05T19:40:56.082Z

the weird thing is that the code works, even in mongo shell , when i do load(myfunction.js);

takis_ 2021-06-05T19:41:24.082800Z

i can call it as add_cj(1,2); fine , but when i send it as string it says reference not found

thheller 2021-06-05T19:42:00.083400Z

the ^:export is likely the problem. that wants to export the whole thing into the global scope, which may not be allowed or blocked for security reasons

takis_ 2021-06-05T19:43:13.084400Z

in the past it worked, i dont know why , i used that code in MongoDB , maybe i changed something i dont know or MongoDB new version blocked something

takis_ 2021-06-05T19:43:41.085Z

all i want is 1 Clojurescript function to become 1 Javascript function

thheller 2021-06-05T19:43:49.085300Z

maybe something like

(ns tempproject.tempnamespace)

(defn my-fn [a b]
  (+ a b))

(my-fn js/arg__0 js/arg__1)
with your add_cj wrapper

takis_ 2021-06-05T19:45:04.085600Z

yes but this will not generate 1 javascript function

takis_ 2021-06-05T19:45:20.086Z

mongoDB expects 1 javascript function not any js code

thheller 2021-06-05T19:45:34.086300Z

your wrapper creates that fn

takis_ 2021-06-05T19:46:14.086700Z

ok i will try to make the call from clojure thank you : )

JuĪ»ian (he/him) 2021-06-05T20:22:41.087500Z

is there an easy way to do sha256 in ClojureScript?

thheller 2021-06-05T20:26:17.087700Z

goog.crypt.Sha256, goog.crypt in general

JuĪ»ian (he/him) 2021-06-05T20:28:25.088Z

thanks

takis_ 2021-06-05T23:47:25.090Z

i am trying long time the js/arg__0 js/arg__1 arguments dissapear on advanced compile, i tried to make the code more complicated like (apply myfn [js/arg__0 js/arg__1]) and it worked, but code from 2k characters gone to 91k characters

takis_ 2021-06-05T23:48:39.091Z

also i need to add a function(arg__0,arg__1) and a return , i need return also

thheller 2021-06-05T23:49:41.092100Z

note that you should expect 91k for any function you write that uses any of the cljs datastructures. it'll only stay small if you stick to very basic JS interop. you probably need externs to prevent the unwanted renaming.

thheller 2021-06-05T23:50:18.092300Z

oh right I forgot about the return, too tired to think about that one now šŸ˜›

takis_ 2021-06-05T23:51:07.092900Z

is there a way to prevent the rename? i dont know how to use externs

takis_ 2021-06-05T23:51:28.093400Z

dont worry you helped me anyways

takis_ 2021-06-05T23:52:44.094400Z

i might benchmark the 91k , because probably i wouldnt avoid it anyways

thheller 2021-06-05T23:53:42.094700Z

yeah I'd expect that as a baseline