This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-21
Channels
- # announcements (13)
- # babashka (63)
- # babashka-sci-dev (64)
- # beginners (37)
- # biff (1)
- # calva (10)
- # cider (7)
- # clj-kondo (15)
- # cljsrn (6)
- # clojure (26)
- # clojure-dev (10)
- # clojure-europe (34)
- # clojure-france (9)
- # clojure-nl (2)
- # clojure-norway (36)
- # clojure-uk (5)
- # clojurescript (142)
- # community-development (1)
- # conjure (3)
- # datalevin (5)
- # datalog (2)
- # datomic (5)
- # events (11)
- # fulcro (40)
- # gratitude (9)
- # guix (32)
- # honeysql (10)
- # jobs (2)
- # lsp (32)
- # malli (15)
- # meander (5)
- # membrane (43)
- # missionary (3)
- # nextjournal (9)
- # off-topic (38)
- # pathom (3)
- # polylith (30)
- # portal (78)
- # programming-beginners (4)
- # quil (6)
- # re-frame (20)
- # reagent (21)
- # remote-jobs (2)
- # shadow-cljs (7)
- # tools-deps (6)
- # xtdb (23)
This is what my project folder looks like today. I have no idea what could possibly have caused this. It's a shadow-cljs reagent webapp. They are all empty and date from the same time Saturday: -rw-rw-rw- 1 pepijn pepijn 0 19 mrt 15:24 ''$'\300\266''W'$'\250\371\177'
I wasn't even working on my app in the weekend I think?? I'm just completely baffled and posting in case anyone has seen something like this before or any suspicion what it could be. They are not even valid UTF-8 or anything. It's nothing like the occasional :w
file or whaterever. Just huge swaths of random binary filenames with no content, all created at the same time.
Are you sure you didn't run something like cat /dev/urandom | xargs -0 -l touch '{}'
? :)
No clue but an error in some script would definitely be my first guess.
Happens every time.
But yeah, that was just to demonstrate the principle. Although lengths of your file names are quite uniform, so it's unlikely to be completely random.
You have .histfile
or something like that in your shell - check what you were running in that time period.
389 git commit -am "new design, fixes #53"
390 git push
391 sudo pacman -Syu
392 klayout
393 klayout --edit
394 klayout --help
395 klayout -h
396 klayout -e
397 git status
398 git checkout master
399 git diff
400 git stash
401 git checkout master
402 git pull
403 make blinky-tangnano-synth.json
404 code blinky-tangnano-synth.json
405 yosys -p show blinky-tangnano-synth.json
The first item is a commit on friday, the next git commands are in a different project. Of course when I opened VS Code on saturday it opened into the last project, so the only thing I can imagine that the act of opening VS Code and then immediately switching to another project caused it to shit the bed.I'm 99% sure it happened after the last klayout command and before the next git command.
whoa that is quite a bug...
Quite funny that it seems to be the C++ plugin, but it created random files in the Cljs project rather than the C++ project I switched to.
in case you are from russia or belarus it might also be https://twitter.com/bantg/status/1504213698658938881
I should have a Dutch IP, but yea that's completely insane.
guess I'll only run npm through docker or so in the future. can't trust this shit anymore.
Technically, you can't trust anything. Well, maybe only backups. No reason same thing couldn't happen with e.g. Maven. Quite easy to miss if you don't check transitive dependencies. Sure, people don't use ranges - but the potential to do harm is still there.
A related problem is that npm is not immutable. So you can unpublish a package and break everyones dependencies.
I am trying to do (ns-map 'my.ns)
from a cljs REPL (in lumo), but I get an error telling me that the ns-map
var is undeclared. It works fine in the clj
REPL. Is ns-map
not available in ClojureScript?
I need a spread operator. 😃 I'm trying to make a library accept a log function and want to provide taoensso.timbre/log
. But that is a macro. (fn [& msgs] (t/log msgs))
makes me log a list...
Could you do something like
`(fn [& msgs] (t/log ~@msgs))
That doesn't compile for reasons. I can do
(fn [& msgs] (t/debug `(~@msgs)))
But that just gives me the list 😃Split the difference?
(fn [& msgs] `(t/log ~@msgs))
Why not apply ?
Oh t/log
is a macro
@pez just use the underlying function - a basic rule of macro writing is that it should be sugar - and that some explicit lib fn call will also suffice
This particular underlying function is a beast to use. Not a very friendly API for the users of my lib. 😃 https://github.com/ptaoussanis/timbre/blob/7bb3d648e1a49cf835233785fe2c07e43b2395da/src/taoensso/timbre.cljc#L526
I mean, my lib would just take a variadic function with the stuff to log, but for the lib users to provide it...
I guess the answer is that this is not possible to do in a convenient way when using timbre logging.
Somewhat related: https://github.com/ptaoussanis/timbre/issues/132#issuecomment-148885343
I submitted it as a question. Seems like a huge ask as a feature request. 😃 https://github.com/ptaoussanis/timbre/issues/350
Seems like this should be possible if I almost do what @U050B88UR suggested and go one step down the abstraction layers. Peter T suggests using the log!
macro. Though I haven't figured out just how yet. 😃
Turned out it wasn't really supported yet, even if that was the intention. Peter T is amazing. I've just tested version 5.2.0-SNAPSHOT and there I can wrap the log!
macro like so:
(fn [& msgs] (t/log! :debug :p msgs))
I am trying to convert an ajax request to cljs. Here is the jquery version
$.ajax({
type: 'GET',
url: '',
data: {
_catalog: "getbitoutdoors1",
_f: 3,
_nrt: 1,
_id: sku,
_code: sku
},
async: true,
crossDomain: true,
success: function(data) {
console.log(data);
}
},
dataType: 'jsonp'
});
here is my test version
(:require
[lambdaisland.fetch :as fetch]
[promesa.core :as p]
[goog.object :as gobj]
[cljs-bean.core :refer [bean ->clj ->js]])
(let [sku "test123product"
fourp-inventory-api-url
""]
(p/->
(fetch/get fourp-inventory-api-url
{:mode :no-cors
:content-type "jsonp"
:accept "jsonp"
:query-params
{:_catalog "getbitoutdoors1"
:_f 3
:_nrt 1
:_id sku
:_code sku}})
js/console.log))
But I cant seem to get the data I can get from js side. As far as I can tell, response body is Null. Is using fetch the right approach? How can I return clojure data to inspect the result easier? (when I tried using js->clj
or ->clj
it still shows an object in the console (only full of meta atm).body nil
but the response body is nested in the returned js object. Hard to see clearly what is being returned. Maybe I’m not doing the promise right?
Possibly a cors issue?
This url is an external api. The working js ajax function is in some blessed theme code. I am trying to weave in some cljs, using shadow-cljs :target :npm-module
and calling the cljs from js.
You're using all 3 of the libraries that I try my best to avoid at all costs. :D Can't really say whether it's your doing or their doing that something doesn't work.
promesa
is absolutely unnecessary when you don't do heavy promise work. And when you do such work, you might have better luck with core.async
.
lambdaisland.fetch
is a thin wrapper about built-in js/fetch
- I myself prefer regular and predictable interop over a library that not only might have potential bugs but also brings in a whole bunch of other dependencies, including a completely different promise library.
cljs-bean
is rarely needed given that interop just works. It's completely unneeded if you don't convert keywords to strings and back during interop. And it also has a bunch of peculiarities that you have to know.
> Possibly a cors issue? When anything strange is going on with your network requests, you should first check the JS console and the Network tab in your browser's DevTools. If there are errors - you will see them. If the response body is not what it's supposed to be - you will see it.
I realized I was running both versions on the same pageload. Turned the ajax one off. I can see from the network tab that the request is working, and the response data is there! But I’m not sure how to pull it out of all this.
The response is there. But the data doesn't seem to be - :body
is set to an empty string.
BTW you should definitely use https://github.com/binaryage/cljs-devtools
I can try simple js interop. I am not a strong js dev, so I was hoping for solid abstractions, but you know how that goes:unicorn_face:
You don't need to be a JS dev to use built-in JS API. MDN has great resources, and most of the things are very easy. And stuff that's not easy can't have a solid abstraction anyway.
Can you do something like this:
;; turn this
js/console.log
;; into this
(fn [resp]
(js/console.log (clj->js resp)))
The body is probably null
because it's not proper json?
jsonp ? I google this + cljs and couln’t find anything
just put [binaryage/devtools "1.0.5"]
in shadow-cljs.edn :dependencies
?
That simplified the console result But still empty string
I try to implement the simpler fn.
Should I be using something like cljs-http instead of fetch?
If you really want a wrapper, you can use anything you want. lambdaisland.fetch
should be fine as well - assuming you know its API and how to use it. But same thing applies to any other library or built-in thing, including cljs-http
or js/fetch
.
When I'm doing requests myself, I just use js/fetch
. When I'm doing requests via re-frame, I'm transitively using cljs-http
just because the :http-xhrio
effect uses it.
What is your fetch method to encode query params?
I have a ~5 line function that uses https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
I still cant get the value out of there :thinking_face: Gotta stop for now. When I have more time I will try to implement a query param encoder. Thank you for the help though!
The data is in the reponse in the network tab.
([{"test123product":["test123product,12455,0","test123product-BL,Test Product - Do not remove Color = Blue,20","test123product-GR,Test Product - Do not remove Color = Green,0","test123product-RE,Test Product - Do not remove Color = Red,0","test123product-ST,Test Product - Do not remove Color = Stock 0,0","testnewsku,Test Product - Do not remove Color = Unavilable,0"],"total":20}])
Hopefully I can access it easily when I learn better interop.Also, the data that you're sending is strange. It looks like a JSON array but wrapped in parentheses for some reason. Doubt any of the decoders knows how to deal with that - maybe that's where the problem lies, like Mitesh mentioned above.
That is the data that is being fetched. Maybe it’s jsonp?
what is you opinon on the js-interop lib? Same as cljs-bean?
> That is the data that is being fetched.
I understand that. But why is it being served that way? Is there a content-type
header that specifies what type it's supposed to be?
> what is you opinon on the js-interop lib?
In the age of externs inference and when we have goog.object
and built-in interop, such libraries are completely unneeded.
content type: text/html ? This app we are requesting from (we don’t control) is definitely random and shoddy.
> Maybe it’s jsonp? jsonP usually has a callback which is provided -or- a default callback returned. This just looks like malformed JSON, check the server why it's adding those extra round parens.
^or check if you can provide it a callback
param like ?callback=myJsonPCallbackFunc
I am only on client side. Ok I’ll try that.
Also can you change
:content-type "jsonp"
:accept "jsonp"
to just "json"
I havent implemented a bespoke fetch fn yet with the query params. But if I can just get the string I can parse that.
I tried that. Same result.
> But if I can just get the string I can parse that.
If you want this try to remove the :content-type
options from fetch. If a content-type is added, we try to parse using that
Feel free to hit it yourself if you want, It’s an open api.
otherwise we return the body as is
Sure give me a sec Ill try it out 🙂
I tried omitting the content-type too, no change.
Whatever that API is, it's not that great.
Given how it has added ()
, I would make sure to either find a better API or to at least find proper documentation on this one. Who knows what else they might've invented.
They are a “Total Mess”!!! I probably should have set up a proxy server to route around them long ago. But for now it’s the only live inventory data I have.
btw the front end for this inventory/shipping product looks like it was frozen in web 1.0!
Then you'll have to read the body as a string, chop off the starting (
and the ending )
and parse the rest with js/JSON.parse
.
Any pointers how to read body? I can’t find that string in my response data.
If I go to one of these urls I see the string in page. Is that normal? https://4plx.com/ssl/yahoo-inv-product_x.php?_catalog=getbitoutdoors1&_code=Batson_XBPPLT08R07.0&_f=2&_id=ALPS_XBPPLT-
> Any pointers how to read body? I can’t find that string in my response data.
Start with plain fetch
in the JS console, learn how to read the body there, then use interop to write the same thing in CLJS and process the body in CLJS.
And also, there's definitely CORS at play - I couldn't use fetch
within the browser from a different domain.
@U09D96P9B The problem is that the above API doesn't return proper CORS headers.
When you use :mode :no-cors
it only supresses the exception, client js still can't access the api response
There is no way around this except for setting up a proxy serevr
Right. If you have a backend, make that request on the backend instead. If you don't have a backend, there are CORS-"fixing" thirdparty proxy servers out there, easy to find.
I guess the jquery ajax theme code is dealing with the cors better somehow. Same codebase. When I run it in the console I definitely see cors errors.
So even if my devtools network response view shows the data from the request, my code might still not be able to get it (because of cors issues)? I guess that make sense from a security standpoint…
Maybe that is what jsonp does, get’s around the CORS issues?
test123product
Browserfor reference: cljs-http has some accomodation of jsonp https://github.com/r0man/cljs-http#jsonp
> Requesting a file from another domain can cause problems, due to cross-domain policy.
> Requesting an external script from another domain does not have this problem.
> JSONP uses this advantage, and request files using the script tag instead of the XMLHttpRequest
object.
https://www.w3schools.com/js/js_json_jsonp.asp#:~:text=JSONP%20stands%20for%20JSON%20with,instead%20of%20the%20XMLHttpRequest%20object.
Looks like someone had to use jquery itself from cljs to do something like this. https://gist.github.com/mjg123/1098417
I'm rather confused and very intrigued because I don't understand how jQuery manages to work around this.
LOL, yeah, you're right - jQuery just adds a <script>
tag and removes it right after the response is received.
That's why ()
are not a problem.
> JSONP is vulnerable to the data source replacing the innocuous function call with malicious code, which is why it has been superseded by https://en.wikipedia.org/wiki/Cross-origin_resource_sharing (available since 2009https://en.wikipedia.org/wiki/JSONP#cite_note-caniuse-cors-3) in modern applications.
That's some ancient API you're using. Or it was written by ancient people. :)
Given that quoted statement, I wouldn't be that eager to trust it. I'd probably try to use a proxy and regular JSON.parse
instead.
I tried this, but gettings errors
(let [inventory-api-url
""
jsonp (goog.net.Jsonp. (Uri. inventory-api-url) "jsoncallback")]
(.send jsonp nil success-handler error-handler))
via https://stackoverflow.com/questions/31349911/how-to-implement-a-jsonp-callThanks for the feedback. I’ll probably just use the jquery to feed the data to my cljs for now. And look for alternatives like you mention.
It seems that GCC now requires you to use goog.html.TrustedResourceUrl
instead of goog.Uri
when it comes to JSONP.
Also note that you don't need to use goog.net.Jsonp
when you use the import
from the SO post - you can just use Jsonp
.
Trouble with all of that, as that quoted statement says, is that if 4plx
sends you some malicious code instead of the data that you expect, that code will be executed on your very web page. It can do anything.
> That’s some ancient API you’re using. Or it was written by ancient people. :) I love these quotes. I can use them to share with my boss why I’m not off the deep end when I’m burning lots of time figuring out the inane behaviors of this product for potential integrations.
:D Happy to help
Hmm, the TrustedResourceUrl
approach still doesn't work "because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled."
jQuery does more "magic" than I realized.
Oh wow, OK. jQuery listens for the load error
event and treats the error as a success.
This whole approach is what people call jugaad.
> treats the error as a success These inconsistencies confirm my aversion to js. But i will take your advice to heart and use the pure stuff more directly.
If I REALLY needed to write this in cljs. Could I do the jquery magic myself?
Certainly - it's just JS code. You can extract the relevant parts and load them from a JS file or rewrite them in CLJS.
I was forged in IE6 days (more like 10 years), so I’ve been very jaded. Which is why i found Clojure! :smiling_face_with_3_hearts:
Yeah, same, although I was fortunate enough to mostly deal with backend and desktop programming in that era. Fortunately, modern JS is much nicer. But not without its issues, of course.
And to be fair, this whole issue is orthogonal to the language - it's just an artifact of the history of web browsers' security.
Is this correct way to append color? [:div.label-message {:color "#F4847CD"} "POPUP"}]
What do you mean by "append"? With that hiccup, you're specifying a particular text color on the element (well, not only text, but mainly text).