Thomas. Your docs are amazing. Thank you! It has helped me make sense of ClojureScript macros. π
Is it possible to write a macro that uses an npm package as a dependency? Iβve run into Gotcha #1: Namespace Aliases and Dependencies from https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html. My goal was to write a quick utility for faking timers in tests with @sinonjs/fake-timers but it seems like thatβs not possible with deps from npm. :/ my.util.clj
(ns test.fixtures)
(defmacro with-fake-timers
[symbol & body]
`(let [~symbol (fake-timers/install)]
(try ~@body
(finally (.uninstall ~symbol)))))
my.util.cljs
(ns test.fixtures
(:require
["@sinonjs/fake-timers" :as fake-timers])
(:require-macros
[test.fixtures :refer [with-fake-timers]]))
my.util-test.cljs
(ns test.fixtures-test
(:require
[cljs.test :refer [deftest testing is]]
[test.fixtures :refer [with-fake-timers]]))
(deftest macro-test
(is (= '_ (macroexpand-1 '(with-fake-timers clock (prn "Hello, world"))))))
(deftest with-fake-timers-test
(testing "Given a symbol to bind to and a body to execute, "
"it should replace the global timer APIs and execute the body"
(let [previous-value js/window.setTimeout]
(with-fake-timers clock
(let [actual (= js/window.setTimeout previous-value)
expected false]
(is (= actual expected)))))))
Could this be related to it being a :karma build target? The macro expands as expected but uses the missing ns alias, then throws: > Chrome Headless 88.0.4324.150 (Mac OS 10.14.6) test.fixtures-test with-fake-timers-test FAILED > FAIL in (with-fake-timers-test) (ReferenceError:NaN:NaN) > failed with ReferenceError: fake_timers is not defined > message: Uncaught exception, not in assertion. >
Iβm guessing I should stop fighting and give up on the macro. π
hihi, I'm trying to use shadow-cljs where I need to consume some javascript generated by the typescript compiler. I've tried different ways to transpile and I just don't seem to be getting it right.
If I transpile in ES2015+, shadow-cljs complains about references to import * as cdktf from 'cdktf';
. If I transpile to CommonJS, it complains as well:
; Execution error (ReferenceError) at (<cljs repl>:1).
module$docker$index is not defined
with which shadow-cljs version did you try? I fixed a bug related to this very recently. try 2.11.17
"shadow-cljs": "^2.11.17",
@thheller: looks like the same version βοΈ
on problem is that for all npm dependencies the closure compiler will see them as commonjs
thus import * as cdktf from 'cdktf';
is invalid and would need to be import cdktf from 'cdktf';
. which the warning is telling you basically
@thheller: ok, so that's something I'd need to manually change after the transpiler completes if I want to target ES2015? But if it's CommonJS as the target and I'm getting module$docker$index is not define
-- what should I do in that case?
regarding ES2015 output and your suggestion about manual change, magic!
> docker
#js {:Config #object[Config$$module$docker$config], :Container #object[Container$$module$docker$container], :ContainerNetworkData #object[ContainerNetworkData$$module$docker$container], :DataDockerNetwork #object[DataDockerNetwork$$module$docker$data_docker_network], :DataDockerNetworkIpamConfig #object[DataDockerNetworkIpamConfig$$module$docker$data_docker_network], :DataDockerRegistryImage #object[DataDockerRegistryImage$$module$docker$data_docker_registry_image], :DockerProvider #object[DockerProvider$$module$docker$docker_provider], :Image #object[Image$$module$docker$image], :Network #object[Network$$module$docker$network], :Secret #object[Secret$$module$docker$secret], :Service #object[Service$$module$docker$service], :Volume #object[Volume$$module$docker$volume]}
> Container
#object[Container$$module$docker$container]
I don't know. can you try with a browser-repl
or an actual build?
I didn't make any changes to the references or to the shadow-cljs.edn
after transpiling to ES2015 and changing the import statement for every single generated .js file
note, my current ns where it's working with ES2015 now:
(ns demo.script
(:require ["constructs" :refer (Construct)]
["cdktf" :refer (App TerraformStack)]
["/docker/index" :as docker :refer (Container)]))
what should I look for in a browser-repl
for this?
here's my shadow-cljs.edn
:
{:source-paths ["src/main" ".gen/providers-out"]
:builds {:app {:target :node-script
:output-to "target/script.js"
:main demo.script/main}}}
browser-repl for the cases where you get module$docker$index is not defined
now
if things even run in the browser. seems to be a node target so that may not be an option.
ya, it's definitely a node target
I'll go with the ES2015 module output for now, thanks! I'm not sure how I would've troubleshooted this without you.
> tree ./.gen/providers-out/
./.gen/providers-out/
βββ docker
βββ config.d.ts
βββ config.js
βββ container.d.ts
βββ container.js
βββ data-docker-network.d.ts
βββ data-docker-network.js
βββ data-docker-registry-image.d.ts
βββ data-docker-registry-image.js
βββ docker-provider.d.ts
βββ docker-provider.js
βββ image.d.ts
βββ image.js
βββ index.d.ts
βββ index.js
βββ network.d.ts
βββ network.js
βββ secret.d.ts
βββ secret.js
βββ service.d.ts
βββ service.js
βββ volume.d.ts
βββ volume.js
1 directory, 22 files
all the exports are within index.js
and the modules it refers to call out to cdktf
(expected from node_modules
)
any help would be much appreciated π
for CommonJS:
> (require '["/docker"])
FileNotFoundException: ~/hello-world/.gen/providers-out/docker (Is a directory)
> (require '["/docker/index" :as docker])
nil
> docker
Execution error (ReferenceError) at (<cljs repl>:1).
module$docker$index is not defined
nil
for ES2015:
ExceptionInfo closure errors {:tag :shadow.build.closure/errors, :errors [{:resource-name "docker/config.js", :source-name "docker/config.js", :line 3, :column 0, :msg "Namespace imports (goog:some.Namespace) cannot use import * as. Did you mean to import cdktf from 'goog:shadow.js.shim.module$cdktf';?"}]
and here's how the module looks like in the node REPL after transpiling to CommonJS:
> var docker = require('./.gen/providers-out/docker')
undefined
> docker
{
Config: [Getter],
ContainerNetworkData: [Getter],
Container: [Getter],
Image: [Getter],
Network: [Getter],
Secret: [Getter],
Service: [Getter],
Volume: [Getter],
DataDockerNetworkIpamConfig: [Getter],
DataDockerNetwork: [Getter],
DataDockerRegistryImage: [Getter],
DockerProvider: [Getter]
}
@sean.poulter the easiest path is just creating a function in CLJS that delegates to the npm dep (defn install-timer [] (fake-timers/install))
and call that from the macro instead.
Thanks for keeping it simple. π
That works perfectly. π
Do you have a preference for Patreon or PayPal?
Wouldn't it be useful to also take into account file deletions when it comes to live reloading? (Eg. UI reflects that a CSS file has been deleted (browser will reload non-existing file))
how would it reload a non-existing file? doesn't make much sense to me
all fine π
Do what it does for modifications (ie. modify the r
query argument -> browser tries to reload file and fails)
yes but why would you willingly force a 404?
For instance in the context of live reloading CSS, it's a bit confusing that nothing changes when a CSS file gets deleted (because the browser knows nothing about that)
yeah still no clue what you are doing but so far I'm not interested in adding that
Haha, all right, it's just I would expect that deleting any live-reloaded asset that is still being used by my code would induce a change to help me notice it, but all right
yeah I can only imagine getting into weird situations. the only sensible things to do would be deleting the link
tag used to import the style as thats the only way to remove the css
but then when you add it again the HTML doesn'lt have the link
anymore so it won't be loaded
in general you should only have one css file anyways. at least thats what I have always done. take the many files and generate one that is loaded in the html