Fork me on GitHub
#clojurescript
<
2017-09-27
>
seako00:09:16

hello, i’m trying out the new npm-deps feature of cljs. i’m trying to require an addon from the codemirror project and when i build my app i get the following error:

java.lang.AssertionError: Assert failed: cljs.analyzer/foreign-dep? expected symbol got "codemirror/addon/edit/matchbrackets"
my ns declaration looks like the following
(ns my-app.web.components.editor
  (:require
    [codemirror :refer [CodeMirror]]
    "codemirror/addon/edit/matchbrackets"
    "codemirror/addon/edit/closebrackets"
    "codemirror/addon/hint/show-hint"
    "codemirror/addon/hint/sql-hint"
    "codemirror/mode/sql/sql"
    [reagent.core :as reagent]))

seako00:09:19

from the recent post about npm-deps https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules i thought that strings were permissible in ns declarations? but i suppose i was wrong. any help getting me pointed in the right direction would be much appreciated.

seako00:09:40

oh, in case it’s helpful, this is the implementation matchbrackets file https://github.com/codemirror/CodeMirror/blob/master/addon/edit/matchbrackets.js

briantrice00:09:07

“arriving in the next version of ClojureScript” is pretty vague. I’m new and don’t know what version that might be, but it’d have to be recent

sundarj08:09:25

cljs versions use the number of commits to master since the last major release (e.g. 1.9.908 means '908 commits since 1.9')

seako00:09:45

i’m using 1.9.908

briantrice00:09:06

no idea. I’m on an older version.

seako00:09:21

thanks anyway

anmonteiro00:09:49

@seako strings are valid, probably a problem parsing your module. can you put together a minimal repro I can look at?

seako00:09:46

yeah, i can give that a go

benny04:09:04

how do i go about writing and running unit tests in clojurescript?

benny04:09:00

I’ve created tests as i understand they’d be written in plain clojure with clojure.test but when i run lein test it runs 0 tests

noisesmith04:09:44

right, lein test doesn't load your clojurescript - there are frameworks to set up and run cljs tests, but essentially all you need is to have a running cljs repl, load all the source files that contain tests, and run them with cljs.test/run-tests https://clojurescript.org/tools/testing

benny04:09:17

it seems like in here https://github.com/emezeske/lein-cljsbuild/blob/master/doc/TESTING.md that it’s possible, but the configuration interacts with phantom and doesn’t utilize clojure.test there’s no way to change that to use clojure.test instead is there?

noisesmith04:09:20

you can make the function you hand it run anything you like in phantom...

noisesmith04:09:23

clojure.test is probably the easiest thing to use in that function - but there are definitely other options for leiningen cljs test tooling -- for example I've frequently seen doo mentioned (but haven't used it myself - I just made an alternate cljs build, with the same cljs source paths, and a page that loads that build and invokes my test runner in a script tag - that way I can run tests in the same browser my code is supposed to support) - https://github.com/bensu/doo

noisesmith04:09:26

from skimming the doo readme, it looks like they also prefer making a seperate cljs build with your tests as a target

benny04:09:49

so if i understand it, looks like i would just do something similar to this? https://github.com/emezeske/lein-cljsbuild/tree/master/example-projects/advanced

noisesmith04:09:04

I guess - though they aren't even using a test library, they just have some functions that call assert

Oliver George10:09:37

Does the :foreign-libs feature provide any support related to source maps?

Oliver George10:09:08

I'd like mylib.js.map to be copied alongside mylib.js

Oliver George10:09:41

That way chrome would pick up the source mapping when debugging with :optimisations :none

Oliver George10:09:11

Ah, found a related ticket. Looks like its a welcome feature waiting for a developer...

Oliver George10:09:31

With that in mind, I'd love to hear any workarounds for copying extra files as part of the compilation

thedavidmeister13:09:59

how often/when are foreign libs (re)downloaded?

dnolen14:09:35

@thedavidmeister not sure I understand the question

dnolen14:09:42

foreign libs are not downloaded

dnolen14:09:05

it’s your tool that specifies your deps

dnolen14:09:11

some of those deps may have foreign deps in them

dnolen14:09:26

how often something gets downloaded is a Maven thing

dnolen14:09:40

but generally once, it’s cached globally on your machine

thedavidmeister14:09:38

if i do :file and put a url in, that has to download it though right?

Oliver George22:09:58

With :optimisations :none those files are copied into the output path. The browser will GET the file when it's required in a namespace.

Oliver George22:09:21

In that case the browser fetches each namespace or foreign lib separately.

Oliver George22:09:35

For a production build it's all bundled up into a single js file.

thedavidmeister02:09:54

@U055DUUFS so if i have 10 foreign libs, then i have to download those 10 files every time i compile cljs?

Oliver George03:09:03

I've never used urls in my build process.

Oliver George03:09:14

My foreign-libs are precompiled js files which sit in the repo.

Oliver George03:09:31

So not much different to regular source code really.

Oliver George03:09:22

you might find this doco interesting if you're unfamiliar with foreign-libs

thedavidmeister04:10:09

those docs don't really answer my q unfortunately

thedavidmeister04:10:59

i'll try putting them locally though, worth a try 🙂

thedavidmeister13:10:25

i converted everything to local and the speed was identical fyi

thedavidmeister13:10:32

so it must cache the downloads

Oliver George08:10:32

Interesting. Good to know.

daiyi14:09:37

hm hmmm if I try to feed a colon into cljs's read-string, I get an exception. How do I either get nil instead of an exception, or check if something is valid for reading before feeding it into the reader?

cljs.user=> (cljs.reader/read-string ":")
#object[TypeError TypeError: Cannot read property '0' of null]
   cljs$reader$read_keyword (jar:file:/home/u/.m2/repository/org/clojure/clojurescript/1.9.89/clojurescript-1.9.89.jar!/cljs/reader.cljs:359:21)
   cljs.reader/read (jar:file:/home/u/.m2/repository/org/clojure/clojurescript/1.9.89/clojurescript-1.9.89.jar!/cljs/reader.cljs:456:22)
   cljs$reader$read_string (jar:file:/home/u/.m2/repository/org/clojure/clojurescript/1.9.89/clojurescript-1.9.89.jar!/cljs/reader.cljs:469:6)
nil

daiyi14:09:57

I feel like I'm using read-string improperly (':

reefersleep16:09:05

I think you might be. read-string expects a clojure (or cljs) data structure, as far as I understand, and : is hardly a valid clj/cljs data structure 🙂 I tried entering : into a clj repl to see what it would evaluate to, and it caused an exception as well.

daiyi16:09:46

haha yes, : is not valid. I am taking user input though, so I can't control what goes in.

thedavidmeister02:09:07

@daiyi from memory there are options you can pass to read string to determine whether it throws an error or returns info that it wasn't valid - can't remember if that was clj or cljs or both though

daiyi04:09:27

I think that's for reader, rather than read-string. I can't figure out how to use reader, I think it needs a stream? https://clojuredocs.org/clojure.core/read

thedavidmeister07:09:43

yeah, i think i was wrong about that

thedavidmeister07:09:47

i think this is it

thedavidmeister07:09:40

seems like you need to either try/catch or find a function that just determines the validity of edn without trying to parse it

mhuebert15:09:52

+1 for try-catch, it will do exactly what you are attempting. (try <some expr> (catch js/Error e nil)). You could also then inspect the error and react differently depending on what happened. Below is an example of that, though a bit complicated because of cljs/clj reader conditionals: https://github.com/braintripping/magic-tree/blob/master/src/magic_tree/parse.cljc#L153 there is an option you can pass to read-string to avoid throwing an error on “end of file” (`eof`) errors, but for the rest, exceptions are baked in.

sundarj14:09:15

@daiyi can't you use a try-catch?

daiyi14:09:17

I suppose!

andrea.crotti14:09:23

anyone knows an example of a project that mixes server side rendering with clojurescript? (using re-frame to be more precise)

andrea.crotti14:09:55

so in theory I could just use any templating library on the backend, and just render the HTML with the few interpolations I need

andrea.crotti14:09:00

and then clojurescript will do the rest, right?

joshkh15:09:51

i'm using cljs-http and i need to POST both form params as well as a text/plain body. it looks to me like cljs-http only accepts parameter maps. has anyone come across this problem before? i'm trying to hit this web service API end point: http://iodocs.apps.intermine.org/flymine-beta/docs#/ws-list-append/POST/lists/append

anmonteiro16:09:46

@daiyi From the stacktrace, you seem to be using an older version of CLJS

anmonteiro16:09:00

Is the latest not a possibility?

anmonteiro16:09:44

You should get a much nicer error at least if you use 1.9.908

anmonteiro16:09:56

1.9.89 is waaaay old at this point

daiyi18:09:41

I will try updating! updating stuff is still pretty spooky to me at this point

fenton17:09:54

how do i convert a goog.date.UtcDateTime to a js/Date object?

noisesmith17:09:47

@fenton why are you using Date as a function instead of using . to use its constructor in the first call?

noisesmith17:09:53

because if you used . to access the constructor I think that call would work 😄

fenton17:09:55

time for glasses

fenton17:09:04

yes it does...thanks! 🙂

pat22:09:05

is it safe to use namespace objects as values for an impromptu runtime resolve?

pat22:09:19

I am working through the modules guide. I have a handful of differentiated namespaces, each with identical kit of functions.

pat22:09:08

right now I can manually identify each function but it is verbose, I feel like there could be a dynamic solution

pat22:09:47

inspecting the modules gets me there, doesn't feel wise

thheller23:09:23

@pat no, not safe. resolve at runtime will not work in :advanced optimized code

pat23:09:29

@thheller really i meant getting that functionality. just using the namespace as a pojo and grabbing 'methods'

thheller23:09:04

yes, not safe. sounds like you maybe want a protocol?

pat23:09:20

a protocol on the module itself would be ideal

thheller23:09:17

not sure what you mean by “module”?

pat23:09:16

namespace foo.core and bar.core..... etc. each has functions a() b() ... etc. I split each namespace into a module

pat23:09:36

I want an elegant way to turn foo.core -> foo.core.a()

noisesmith23:09:42

this is what records and protocols are made for - namespaces will never be a good fit for that kind of code pattern

thheller23:09:14

a module is a collection of namespaces but you are using a single namespace in your example?

pat23:09:24

yes its jsut an example

pat23:09:30

these are big heavy namespaces

pat23:09:36

half dozen and counting

pat23:09:54

i can enumerate them fine

pat23:09:03

just feels fragile

thheller23:09:13

I’m not sure what you are trying to do

pat23:09:07

these are all namespaces that riff on the same functionilty. they are not all used at same time, so delivered when user needs them.

noisesmith23:09:21

namespaces are definitely fragile when used as containers / injected dependencies. If what you need is multiple implementations that give different functionality or implementation but having the same basic interface for usage, use records and protocols

pat23:09:26

code-splitting modules is perfect fit

pat23:09:55

*these are not data types*

noisesmith23:09:07

who said anything about data types?

noisesmith23:09:31

if they never hold data at all, use reify and protocols

pat23:09:26

this isnt data its code.

noisesmith23:09:32

right, reify is code

darwin23:09:16

another idea: each namespace can have one exported function returning a map of all functions in the namespace, this would survive advanced optimisations

noisesmith23:09:16

namespaces are a clumsy way to do modularity - it can be done but it’s going to be awkward, but do it however you like of course

darwin23:09:02

@pat you can even use a macro to generate that map automatically, so you don't have to maintain it

noisesmith23:09:05

but a map is data, you said this wasn’t data

thheller23:09:23

namespaces do not exist in :advanced mode, so building anything on top of namespaces is risky

noisesmith23:09:36

(and the main problem with using namespaces this way is they are clumsy as data containers)

darwin23:09:48

get-markup-db fn could be set! on global js/window or anywhere to be consumed by other code

pat23:09:08

thankyou