Fork me on GitHub
#shadow-cljs
<
2022-08-24
>
sirwobin10:08:38

I've just received an error trying to attach metadata to a keyword. I'm targeting nodejs. Is that expected?

bg10:08:23

in Clojure Keywords can’t contain metadata. They don’t implement the IObj interface. CLJS shouldn’t be too different.

👍 1
thheller16:08:01

correct, keywords can't have metadata

Yehonathan Sharvit13:08:51

Can we load a local json file in node.js as part of the ns form?

thheller16:08:14

no, the ns form loads code.

Yehonathan Sharvit17:08:14

Does it mean the only way to do so is through the async fs API?

thheller17:08:14

no? what are you trying to do exactly and in what context?

thheller17:08:07

I mean technically in node targets you can load .json files via the ns require but I don't think you should 😛

thheller17:08:25

(def json (js/require "./that.json")) works too

Yehonathan Sharvit17:08:23

I am building a cljs app that reads it's config from a JSON file

thheller17:08:37

at which point? on program startup?

Yehonathan Sharvit18:08:23

Yes. On program startup

Yehonathan Sharvit08:08:30

What’s the folders where js/require looks for the file?

thheller08:08:32

depends on where it is used

thheller08:08:57

you can also just use (fs/readFileSync "./that.json"), just need to also (js/JSON.parse ...) it

Yehonathan Sharvit08:08:31

> depends on where it is used What do you mean?

thheller08:08:55

well in which context do you use it? is it a :node-script build?

thheller08:08:02

then it is relative to the :output-to file

thheller08:08:31

the fs/readFileSync would be relative to where the node process was started

thheller08:08:03

so usually that is the better option if you want to make it runnable as a package but use a file from outside the package

Yehonathan Sharvit10:08:13

OK. fs/readFileSync is appropriate for me

sirwobin15:08:27

How should one require the nodejs path module? According to https://nodejs.org/api/path.html it's require('node:path'); so I tried (:require ["node:path" :as path]) following along from https://code.thheller.com/blog/shadow-cljs/2017/11/10/js-dependencies-in-practice.html. That doesn't work. Neither does (:require [path :as path])

thheller16:08:50

@sirwobin which build :target do you use? just (:require ["path" :as path]) should be fine (this might be dependent on which node version you use though)

thheller16:08:55

(:require ["node:path" :as path]) should be fine too, but this is all dependent on which :target you use

sirwobin19:08:22

I use :target :node-library with node 18.7.0, and shadow-cljs 2.19.9. Thanks so very much for taking the time to make great software and answer questions. Will have a look at patreon shortly.

sirwobin20:08:26

When I eval my file through a cljs repl I see this error:

Syntax error macroexpanding clojure.core/ns at (src/main/com/pds/external_api/storage.cljs:1:1).
((:require [fs :as fs] ["node:path" :as path] [cljs-bean.core :refer [->clj ->js]] [promesa.core :as p] [com.pds.external-api.config :as config])) - failed: Extra input spec: :clojure.core.specs.alpha/ns-form
Syntax error compiling at (src/main/com/pds/external_api/storage.cljs:9:4).
etc...

thheller20:08:41

that is not a cljs repl. that is a clj repl

sirwobin20:08:52

This only happened when I added "node:path" :as path]

thheller20:08:49

Syntax error macroexpanding clojure.core/ns this is an error from the clojure REPL

sirwobin20:08:55

Hmm, the node client did die a few times... I assumed the repl session would be automatically resumed when it connected to the watch server.

thheller20:08:01

this is not a CLJS error so you are not in a CLJS REPL at all

thheller20:08:16

you can just use shadow-cljs node-repl (or whatever the equiv is for your editor)

sirwobin20:08:57

Each time the node repl provider dies I should send (shadow/repl :lambda)

sirwobin20:08:08

from my nrepl client.

sirwobin20:08:16

to restart the cljs repl session..

thheller20:08:33

I assume you use emacs so I can't really answer any questions regarding that

thheller20:08:43

but no you should never need to restart the REPL ever

sirwobin20:08:47

I think I have enough clues, thank you and sorry to disburb

sirwobin20:08:58

I hadn't realised those were clj repl errors

sirwobin20:08:56

I'm using nvim and conjure. While making node fs functions, the node repl provider would crash if ever my functions returned a js/Error instead of throwing it. Node would just quit. Returning a map with namespaced key seemed a sensible replacement and it works. But discovering that meant restarting the node repl provider quite a few times.

sirwobin20:08:29

Each time I evaled the buffer to reload a namespace, it seemed to resume the repl session very easily

sirwobin20:08:51

and remain in a cljs repl when reconnected.

sirwobin20:08:06

But maybe this hasn't happened always?

sirwobin20:08:40

Just reissued the (shadow/repl :lambda) from my repl and it's resumed the cljs session, Seems I might need to reissue it from time to time.

sirwobin20:08:47

if the node repl provider dies

thheller20:08:22

what is a node repl provider? what do you mean by that?

sirwobin08:08:04

In your notes somewhere you mention to run a watcher process to provide the clj repl and to run node target.js in addition to a watcher to provide a cljs repl that one can access with (shadow/repl :target) So I think of the node process as the repl provider.

thheller08:08:45

ok. I call those the runtime

thheller08:08:07

so the runtime may crash and in case of :node-library you need to manually start it again. that is correct.

sirwobin08:08:11

Got it. How can I recognise clj repl errors apart from cljs repl errors?

thheller08:08:35

you do however not need to run (shadow/repl :target) again normally. the shadow-cljs watch will automatically pick the new runtime when it is started

thheller08:08:52

no clue. I don't use nvim/conjure

sirwobin08:08:24

Spoken like an emacser.

thheller08:08:31

not an emacser either

thheller08:08:45

I use Cursive 😛

sirwobin08:08:48

my mistake 😉

sirwobin08:08:08

Once again, great software 🙂

sb17:08:08

Sorry could you help me, how could I “translate” this to Clojurescript?

const editor = Jodit.make('#editor', {
	buttons: [
		...Jodit.defaultOptions.buttons,
		{
			name: 'insertDate',
			tooltip: 'Insert current Date',
			exec: (editor) => {
				editor.s.insertHTML(new Date().toDateString());
			}
		}
	]
});
Main question is the …Jodit.defaultOptions.buttons part.

Yehonathan Sharvit17:08:06

Use assoc-in or merge

winsome17:08:39

{:buttons (into Jodit.defaultOptions.buttons {:name "my-custom-button" ,,,})} could work as well.

sb17:08:08

thanks!!

winsome17:08:13

Wait, js arrays don't implement ICollection, so that won't work

winsome17:08:05

{:buttons (into (vec Jodit.defaultOptions.buttons) [my custom buttons])}

👍 1
👀 1
sb19:08:25

:extraButtons
tag was the key.. I found in the Stackoverflow..

winsome17:08:16

call vec on it first

sb17:08:55

I check it, thank you very much! 🙂