Fork me on GitHub
#clojurescript
<
2019-04-08
>
manandearth08:04:55

swimming in the dark here... In a CRUD clojure webapp with a Postgresql db, what is the standard (acceptable) way to access the db from clojurescript? (I have clojurescript serving to one of the handlers, db is accessed via the request map on the rest of the handlers which are strictly clj)

vemv08:04:52

Standard approach: the server-side Clojure code should expose a REST API the frontend Clojurescript code should use that REST API via AJAX --- In principle, the frontend should not have direct access to a psql db. It's a security risk

adz5a09:04:35

Hello, you might be interested in this: http://postgrest.org/en/v5.2/index.html if you don't want to write backend code... It exposes a rest api on top of a postgresql DB.

adz5a14:04:14

yep seems so, my bad. there is also rum https://github.com/tonsky/rum that you might want to check out.

manandearth18:04:03

@U2JAS6W2K, yes the postgres api looks really interesting, 👍although I do have the backend ready, It is the retrieval of data by the front-end that I am not familiar with.

myguidingstar07:04:05

@UBGH0Q0H4 there's Edn Query Language (EQL), a Clojure-native standard for client-server communication. EQL is most similar to Graphql

myguidingstar07:04:34

Walkable is a Clojure library to access sql database using EQL http://walkable.gitlab.io/

manandearth08:04:14

very nice, @U0E2YV1UZ, I will definitely try it out. 🙂

Francesco13:04:43

hello guys, I am a Front End guy and I really like Clojure/Clojurescript. Usually, I have been developing apps with Javascript/Typescript and React/VueJS. I am trying to reproduce a similar environment for SPAs in Cljs but I am having a hard time. This is something I am considering: - Shadow-cljs - it would be great to use the NPM ecosystem - Re-frame (or alternatives?) - Re-frame-test for testing - cljss or cljs-css-modules (for css modules) What about linting in Clojurescript? Any suggestion for boilerplates/technologies for SPAs (real-world scenarios)? I hope somebody could help or point me in the right direction, cheers 🙂

adz5a13:04:22

There was a HackerNews thread recently on Fulcro which is a cljs frontend framework. They wrote a full book for developers http://book.fulcrologic.com/ (and hn thread https://news.ycombinator.com/item?id=19520272)

adz5a13:04:59

The book shows the framework but also the whole setup

adz5a14:04:00

For tooling, apart frome shadow-cljs which you mentioned there is figwheel-main wich provides cljs build tool for dev and production, see: https://figwheel.org/

Francesco14:04:22

thank you very much 🙂 figwheel-main is a good point, thanks! not sure regarding fulcro though, it seems more a full stack framework

oconn14:04:36

@UF8BN5KJS I use joker, kibit, and bikeshed for linting / code style, and have a light cljs wrapper around jss https://cssinjs.org/?v=v10.0.0-alpha.16 for styling.

oconn14:04:16

which i have found to be a great experience

Francesco14:04:49

thank you @U1APR44RE!! I believe https://github.com/clj-commons/cljss is similar to what you are mentioning. thanks for the linter options. are you suggesting all of them together?

oconn14:04:57

I use them all together since they mostly check for different things.

Francesco15:04:11

yup, that's what I am noticing 🙂 thanks for your suggestion, I will definitely use those

bontaq15:04:50

I used this https://github.com/Day8/re-frame-template as a starting point, it's been pretty good

Francesco15:04:35

thanks! that looks like a good starting point too

myguidingstar07:04:18

@U2JAS6W2K @UHBF7CA3V Fulcro can be both a frontend and full-stack framework. It's a lot to learn, but web dev is complex already. Re-frame may have a nicer start, but soon productivity decreases quickly due to inconsistency. Every extra tool you'll need to add to your re-frame app is already included in Fulcro without the ad-hoc feeling 😉

Francesco08:04:47

thanks @U0E2YV1UZ for the heads up. I will spend some time with Fulcro and see how it plays with what I am looking for. while I am playing with it, (even though there are lots of resources provided) do you recommend any repo to check particularly? Also, any opinion comparing Re-frame with Rum?

worlds-endless20:04:07

In an old reagent app, I'm having unreasonable difficulty invoking a macro:

worlds-endless20:04:06

I get "can't call setState on unmounted components" error

worlds-endless20:04:42

Is the error in my cljs macro code (I've never written a macro in cljs before)?

lilactown20:04:25

there's nothing that would be changing state in that macro body so my guess is it's an issue somewhere else in your code

worlds-endless20:04:17

Looking via the repl, I see that no matter what I put into body, it seems to be received as nil

worlds-endless20:04:43

Clearly there's something I don't understand here...

thheller20:04:19

@worlds-endless macros are a bit trickier in CLJS and can't be written like that in the REPL

worlds-endless20:04:35

Written in my files, too, my & body never seems to receive anything

thheller20:04:11

macros need to be written in CLJ

worlds-endless20:04:36

Seriously? In 2019?

thheller20:04:58

yep. not going to change.

worlds-endless20:04:51

Thanks... that's the most disappointed in Clojure I've ever been

worlds-endless20:04:33

(which says somethign about how blissful my time in Clojure has been)

Braden Shepherdson20:04:24

I don't know how it can go otherwise - they run at compile time on the host machine.

didibus20:04:48

They can be written in self-hosted ClojureScript

didibus20:04:44

Its logical if you think about it. When do macro run? They run at compile time. What compiles ClojureScript? Clojure does. Macros must thus be evaluated by the compiler. In this case, that's Clojure, and thus the macros have to be written in Clojure.

didibus20:04:38

But, self-hosted ClojureScript is a ClojureScript compiler for ClojureScript code. Thus, if using that, you can write macros in ClojureScript.

worlds-endless20:04:41

@didibus Yeah; makes sense. Just seems like the ugly stepchild I never knew about...

didibus20:04:37

Ya, it does make CLJS a bit more complicated tooling wise. Because it has a dependency on Clojure and JVM as well as the JS runtime you target and ClojureScript

didibus20:04:58

Now, I think it would be possible to build tooling that can be connected to both a Clojure repl and the ClojureScript repl within it. And would be smart enough to eval the macro into the Clojure repl, and somehow reify its evaluation into the ClojureScript repl.

didibus20:04:29

But anyways, don't think that exists right now.

dnolen21:04:53

@worlds-endless I see no one has mentioned that how macros work in ClojureScript is necessary

dnolen21:04:13

the number of people using it would be miniscule today if it wasn't for that early decision Rich made

dnolen21:04:21

self-hosted ClojureScript is 2-3mb before gzipping

dnolen21:04:13

basically 10X larger

didibus21:04:38

@dnolen You mean bundling a compiler into the artifact adds a lot of size to it, which would be detrimental for browser based js targets ? And that was a reason to move the compiler out into Clojure?

didibus21:04:52

Ya, makes sense. I guess though, the compiler could be in a separate Jar. Only used during development for repls

didibus21:04:45

Erm, I guess not Jar, but some JS bundle 😋

lilactown22:04:07

that doesn't help macros

Mno23:04:56

Has anyone used d3 with clojurescript? I’m pretty sure I’m supposed to be getting a map back from this function, but I can’t figure out why it crashes. (I mean I can tell it’s calling length on something undefined, but.. l don’t know what I’m missing..)

lilactown23:04:43

@hobosarefriends you still have the issue where you are double-wrapping things in parens

lilactown23:04:39

cljs.user> ((-> "foo" (str "bar")))
TypeError: ...

lilactown23:04:56

same thing with your anonymous functions

lilactown23:04:02

cljs.user> (def foo #((get-in {:a {:b {:c 1}}} [:a :b :c])))
#'cljs.user/foo
cljs.user> (foo)
TypeError: ...

Alex Miller (Clojure team)23:04:36

In general, you almost never see stacked left parents in regular Clojure code

Alex Miller (Clojure team)23:04:17

(there are some cases with higher order functions that make fns)

Mno23:04:01

@lilactown Oh good you’re still around 😅, woops older example sry I thought i fixed that.

lilactown23:04:23

your error is from the double parens around ->

Mno23:04:49

well im supposed to call the outcome of that one

lilactown23:04:57

have you inspected what is returned by just

(-> (d3/stratify)
               (.id #(get-in (js->clj %1) [:child :uuid])) 
               (.parentId #(get-in (js->clj %1) [:parent :uuid]))

Mno23:04:12

#object[stratify]

lilactown23:04:35

try js/console.log

Mno23:04:47

I did, it returns a function

lilactown23:04:02

if it’s a function, it should be printed like a function

Mno23:04:31

` stratify(data){var i,n=data.length,nodes=Array(n),nodeId,nodeByKey={};for(i=0;i<n;++i){var d= data[i];var node$jscomp$0=nodes[i]=new Node(d);null!=(nodeId=id(d,i,data))&&(nodeId+=“”)&&(d=“$”+(node$js…`

lilactown23:04:43

and TypeError: Cannot read property 'length' of undefined at stratify ( is still the error?

Mno23:04:11

making a thread to avoid bothering people

Mno23:04:24

I mean when I call that function with data

lilactown23:04:35

and what does (clj->js @current-graph) return?

Mno23:04:13

clojure 
#js[#js{:parent #js{:type "EvidenceNode", :uuid "7e1fe71b-b3aa-4f24-898b-22f8623ea230", :url "Because reasons"},
        :child nil}
    #js{:parent #js{:answer "Best Option", :type "AnswerNode", :uuid "affa43ae-3669-4373-81f3-0dad32eee85f"},
        :child #js{:type "EvidenceNode", :uuid "7e1fe71b-b3aa-4f24-898b-22f8623ea230", :url "Because reasons"}}
    #js{:parent #js{:answer "Fourth Option", :type "answer", :uuid "13fca1fc-0bc9-4afc-949d-7b8d43e2154e"}, :child nil}
    #js{:parent #js{:answer "Third Option", :type "answer", :uuid "251560b1-2953-4a4c-9b1e-5edf48e2fe8d"}, :child nil}
    #js{:parent #js{:question "What is better?", :uuid "a89698fc-0aa1-4946-8ad0-7c3ac76eaf9e"},
        :child #js{:answer "Best Option", :type "AnswerNode", :uuid "affa43ae-3669-4373-81f3-0dad32eee85f"}}
    #js{:parent #js{:question "What is better?", :uuid "a89698fc-0aa1-4946-8ad0-7c3ac76eaf9e"},
        :child #js{:answer "Fourth Option", :type "answer", :uuid "13fca1fc-0bc9-4afc-949d-7b8d43e2154e"}}
    #js{:parent #js{:question "What is better?", :uuid "a89698fc-0aa1-4946-8ad0-7c3ac76eaf9e"},
        :child #js{:answer "Third Option", :type "answer", :uuid "251560b1-2953-4a4c-9b1e-5edf48e2fe8d"}}
    #js{:parent #js{:question "What is better?", :uuid "a89698fc-0aa1-4946-8ad0-7c3ac76eaf9e"},
        :child #js{:answer "None", :uuid "3e2ab9d2-f220-47f5-8ddb-dfcdbeb8b72a"}}
    #js{:parent #js{:answer "None", :uuid "3e2ab9d2-f220-47f5-8ddb-dfcdbeb8b72a"}, :child nil}]

Mno23:04:36

ok I managed to get a different error by saving the output of the d3/stratify thing into xyz and then calling it (xyz (clj->js @current-graph)

Mno23:04:08

`Error: multiple roots at stratify (http://localhost:3000/js/cljs-runtime` Which makes a lot of sense since my data has a lot of null children

Mno00:04:26

anyway, thanks dude @lilactown, I’ll try restructuring the data and hope that works.

👍 4