Fork me on GitHub
#clojurescript
<
2021-02-08
>
John Doneth02:02:08

Does anyone have code coverage working with ClojureScript?

hindol05:02:51

Hi! I am trying to follow the official Webpack guide here: https://clojurescript.org/guides/webpack On this command, clj -m cljs.main -co build.edn -v -c -r, I am getting the following error,

{:cmd
  59   │    ["npx"
  60   │     "webpack"
  61   │     "out/index.js"
  62   │     "-o"
  63   │     "out/main.js"
  64   │     "--mode=development"],
  65   │    :exit-code 2,
  66   │    :stdout "",
  67   │    :stderr
  68   │    "[webpack-cli] [Error: ENOTDIR: not a directory, open '/home/<user>/Code/<project>/out/main.js/main.js'] {
       │ \n  errno: -20,\n  code: 'ENOTDIR',\n  syscall: 'open',\n  path: '/home/<user>/Code/<project>/out/main.js/mai
       │ n.js'\n}\n"}
I tried removing main.js from this line in build.edn, :none ["npx" "webpack" "out/index.js" "-o" "out/main.js" "--mode=development"], but that did not help. Any ideas?

hindol07:02:09

Okay, it worked after prefixing all relative paths with ./ and removing main.js from -o. Example,

:bundle-cmd {:none ["npx" "webpack" "./out/index.js" "-o" "./out" "--mode=development"]

Fredrik Andersson08:02:55

So I have dived into ClojureScript and Reagent for a brief time now and I have a couple of questions/concerns that I wish to have opinions on from you experienced clojurists. First: Atoms - I realize that they really solve a problem. But they seem to be used somewhat too easily. Especially when looking at Reagent I feel that it's totally fine to scatter ratoms around. I have read that projects tend to collect the atoms over time up to one major atom, but that seems to be problematic regarding to performance, forcing rendering of the whole tree? I can't find any good explanations or recommendations of how to reason about this. Second: Maps and identifiers - Because that's how anyone structures state. {:myidentifier data} with get-in seems to be the way to access state. However I tend to (def my-deep-data [:myidentifier :substructure :name]) then access a value using (get-in mystate my-deep-data) just to make sure that I get compiler errors everywhere whenever i change my data structure. Third: I use Firestore backend. Which I successfully use thanks to shadow-cljs. The challenge I face is managing long term subscriptions to the server. Turning on and off subscriptions based on different states. Is there any good way to handle this?

phronmophobic08:02:35

have you taken a look at re-frame or fulcro? both of these libraries are aimed at supporting writing more complex user interfaces. if you're already familiar with reagent, re-frame is built on top of reagent and may be easier to get started with

phronmophobic08:02:04

your second point seems to be similar in spirit to re-frame's subscriptions

phronmophobic08:02:37

re-frame also has a story around answering your first question

tvirolai09:02:53

It doesn't make a difference whether you store all your state in a single or multiple ratoms, as changes to it only trigger a re-render to the affected subtree, not the whole DOM.

Fredrik Andersson09:02:53

@U7RJTCH6J i looked at reframe and wasn't totally convinced by the subscription solution because it was still "soft" pointers with strings

Fredrik Andersson09:02:06

@U5JGH2F89 I don't understand how that could work? I thought that the ratoms where the guides where in the tree re-render needed to be done? Or is it diffing the whole vdom and swapping out the changed bits?

tvirolai09:02:53

Correct me if I'm wrong, but I've understood that since Reagent is basically an interface to React, the vdom diffing stuff is delegated to React, which optimizes what needs to be re-rendered.

Fredrik Andersson09:02:19

I think that you are probably right. I just wanted to make sure that it's vdom-diffing that is the technology used.

Fredrik Andersson10:02:11

i have a question regarding delay

Fredrik Andersson10:02:37

sorry, i understand the problem now

🙌 6
Francis Hitchens22:02:22

Hi, this is giving me a headache and any advice would be appreciated. I'm trying to use cljs-node-io {:mvn/version "1.1.2"} in my deps.edn. I got a warning that said this was deprecated and I should use cljs-node-io/cljs-node-io {:mvn/version "1.1.2"}which I did and the warning went away, My source file has this requires in it, (:require [cljs.reader :as reader]            `[cljs-node-io.core :as io :refer [slurp spit]])` but the slurp and spit functions are not defined (nil). What am I missing here? I did see the node-io dependency get downloaded. I get the same error if I try and use it in the repl Execution error (TypeError) at (<cljs repl>:1). Cannot read property 'call' of undefined

p-himik22:02:56

And what is the problem?

Francis Hitchens22:02:58

the slurp and spit functions are not getting created in my namespace and I can't figure out what I am doing wrong. It does not work in the repl either... (require '[cljs-node-io.core :as io :refer [slurp spit]]) (def data [{:foo 42} {:foo 43}] (spit "data.edn" data) Execution error (TypeError) at (<cljs repl>:1). Cannot read property 'call' of undefined

p-himik22:02:32

Ah, I see that you have updated the OP. That shouldn't have anything to do with the way you add cljs-node-io to your dependencies. Both cljs-node-io and cljs-node-io/cljs-node-io are absolutely equivalent. As to why slurp and spit are not defined - no idea. If you can't figure it out, create an MRE and I'll take a look. Just in case - the "Cannot read property 'call' of undefined" error can come from within spit. It doesn't necessarily mean that spit is undefined. Have you tried logging the values of spit and slurp?

Francis Hitchens22:02:06

cljs.user=> (println (type println)) #object[Function] cljs.user=> (println (type slurp)) nil

p-himik22:02:38

I cannot reproduce it at all in a clean NodeJS REPL:

% clj -Sdeps '{:deps {cljs-node-io/cljs-node-io {:mvn/version "1.1.2"}, org.clojure/clojurescript {:mvn/version "RELEASE"}}}' -M -m cljs.repl.node
ClojureScript 1.10.773
cljs.user=> (require '[cljs-node-io.core :as io :refer [slurp spit]])
nil
cljs.user=> slurp
#object[cljs_node_io$core$slurp]
cljs.user=> spit
#object[cljs_node_io$core$spit]
cljs.user=> 

Francis Hitchens22:02:41

Ah, maybe I'm not instantiating the repl correctly. I'm doing a clj -Sverbose -M --main cljs.main --compile json-diff.core --repl

p-himik22:02:48

Do you see a browser window opening when you do that?

Francis Hitchens22:02:02

I tried your command and slurp and spit work just fine.

p-himik22:02:12

> Yes Right, that's because you started a browser REPL. :) But that library is, it seems, designed to be run on NodeJS, in a self-hosted environment.

Francis Hitchens22:02:00

Yes, I have come to that conclusion too. 😳 I'm 4 hours into clojurescript so forgive me please.

Francis Hitchens22:02:06

Thanks for your help. I wonder how I access file from a browser REPL, with a lot of difficulty I guess.

p-himik22:02:15

> how I access file from a browser REPL There's no way to do it automatically - security reasons. Otherwise, any website would be able to read all your files. That's why we have <input type="file>.

Francis Hitchens23:02:02

So if I run a browser repl and have some HTML where I can enter the file or directory name, do you know of a non NodeJS equivalent library to work with the files and directories?

p-himik23:02:53

As I said - you cannot. There's no way. You have to use <input type="file">, click on it (I think this step can be automated), and then select a file manually in the popped-up dialog.

p-himik23:02:30

What is the problem that you're trying to solve that you need to read files in a browser?

Francis Hitchens23:02:12

I want to write a utility that takes two directory tress with a mass of JSON files in them and does a graphical representation of the differences between them based on this Javascript code https://github.com/zgrossbart/jdd.

Francis Hitchens23:02:40

I didn't want to have to learn Javascript too much so I thought to wrap it with Clojure

p-himik06:02:50

Good call. :) See, the demo version of the library above cannot access your folders - it requires you to either paste the data directly or click on the "Choose File" buttons. I'm pretty sure you have only three options here: - Create a full-fledged backend. The server will have access to your file system and the frontend will be able to display it - Create a desktop app. Same as above but with GUI instead of WUI - Create a CLI app that will generate a static HTML and maybe automatically open it in a browser