I wonder if I can somehow set up shadow-cljs to compile to a couchdb design document? https://docs.couchdb.org/en/stable/query-server/javascript.html#commonjs
the design document itself probably no. that looks to be a JSON object not JS code. the example does use require though, so files that can be required and used shadow-cljs can create yes. best via :target :npm-module probably
kinda hard to say. the docs are a bit thin and contain no description of the runtime capabilities
yeah it's a bit unclear. I do know it's the mozilla js engine and not nodejs, and it seems like you may need to (ns views.lib) and then (defn ^:export map)
it may require some additional glue. I doubt it can consume the CLJS code directly
but the doc section you linked has a JS example and a JSON doc
the JSON doc you likely need to write by hand
the JS really depends on the runtime capabilities if it works or not
a release :node-library build will probably work, but the watch/compile probably not since that expects an actual node.js runtime
https://docs.couchdb.org/en/stable/query-server/javascript.html#require
> path – A CommonJS module path started from design document root
dunno what a design document root is, but if you put :npm-module files there they should be loadable
Maybe I shouldn't bother and just write the JS but I kinda want to.
probably takes a few minutes to test, so if you have that go for it. happy to answer questions that come up
what I don't fully understand is how to make sure to export views.lib.map as a function.
like, in
:modules {:demo {:exports {hello demo.lib/hello}}}
what determines the actual exported function?I mean, the namespace of it
I don't have a clue what a view.lib.map function is
like, does my cljs namespace need to be named views.lib or is it irrelevant and do I just need :exports map
I'm just concerned about getting couchdb and clojurescript on the same page on the namespaces
not a clue. that is the couchdb question 😛
JS and couchdb likely do not have namespaces at all
okay so don't worry about it and just export the function under that name
I don't know. :modules {:demo {:exports {hello demo.lib/hello}}} is neither a valid :npm-module config nor a valid :node-library config, so I'm unsure what you are working with right now
eh I just copied that from https://shadow-cljs.github.io/docs/UsersGuide.html#_module_exports
so how DO i export a :node-library function?
that example is :target :esm
something like this?
{:target :node-library
:output-to "out/demo-library/lib.js"
:exports {:hello demo.lib/hello}}
stick to the relevant section 😉
from https://shadow-cljs.github.io/docs/UsersGuide.html#_full_example
yep that gives you a hello export
so with (ns demo.lib) (defn hello [a b] (+ a b)) that is a function that adds the two args
okay I think I'm starting to understand...
ah hmm I think I now understand what they mean by "design document root"
{
"views": {
"lib": {
"security": "function user_context(userctx, secobj) { ... }"
}
},
"validate_doc_update": "function(newdoc, olddoc, userctx, secobj) {
user = require('views/lib/security').user_context(userctx, secobj);
return user.is_admin();
}"
"_id": "_design/test"
}so the validate_doc_update isn't actually accessing any external files
its accesing the views/lib/security section of that doc itself
correct
so yeah, that won't work
why not?
because its basically all one big JSON document
vs. .js files generated and readable from disk
function user_context(userctx, secobj) {
var is_admin = function() {
return userctx.indexOf('_admin') != -1;
}
return {'is_admin': is_admin}
}
exports['user'] = user_contextthis part shadow-cljs can generate, but I'm unsure how this would be used. the docs don't explain it
Yes you'd have to embed the generated js into a json document
"views": {
"lib": {
"security": "function user_context(userctx, secobj) { ... }"
}
},looks like that is just embedded there, which doesn't make sense
I mean I suppose you can write an extra script that takes all the generated .js files and turns then into a big JSON docs, but I wouldn't hold my breath for that actually working
definitely gets more complicated too
well actually a release :node-library build that is manually inlined that way could probably work
{
"views": {
"lib": {
"cljs": "<full node-library release output file contents>"
}
},
"validate_doc_update": "function(newdoc, olddoc, userctx, secobj) {
return require('views/lib/cljs').some_export(userctx, secobj);
}",
"_id": "_design/test"
}like that with (ns demo.lib) (defn foo [userctx secobj] ....) and :exports {:some_export demo.lib/foo} in the config
yeah that is what I'm thinking
I'm only a bit puzzled by
> The lib structure can still be used for view functions as well, by simply storing view functions at e.g. views.lib.map, views.lib.reduce, etc.
Hm maybe I could generate the json in a build hook
can I install clojure build depds somehow? data.json for example. Or just use string interpolation
you can write a clojure function to do that yes. just a regular clojure function that shadow-cljs doesn't need to know anything about.
I was thinking a build hook would be nice since you can just build the js and it'd automatically produce the whole design document but I guess you're limited to core clojure in that case
not really sure what you are thinking
https://code.thheller.com/blog/shadow-cljs/2024/10/18/fullstack-cljs-workflow-with-shadow-cljs.html
in a setup like that. you create a (repl/build-the-thing) function. that function can call (shadow/release :your-build) and after that its just a regular clojure function which can do everything clojure can usually do. including loading and using other dependencies. its just normal clojure, no limits.
yes, you could also do it as a build hook, but I'd keep it separate. makes its easier to experiment and tweak.
heck could even have the function directly upload the thing to the couchdb server
hmmmm
currently I have https://github.com/NyanCAD/Mosaic/blob/main/src/main/nyancad/mosaic/build_hooks.clj
sure that works. but returning the build-state unchanged usually means that this probably shouldn't be a build hook at all 😛
see the example release fn. if you run that instead you basically get the same result, but can structure the code so you can run the function whenever and independent of what shadow-cljs is doing.
okay that's actually a lot nicer now. Any I think I have a cljs view function working!
If I have to add a github repo dependency, is the right move to use deps.edn for that, and if so do I need to use all deps.edn or can I mix deps.edn and the in-line depencencies from shadow-cljs.edn?
you can put them in deps.edn in an alias and in shadow-cljs you can say :deps {:aliases [:foo]} if I recall correctly
I don't know if they mix, I wouldn't be surprised if they didn't
it's documented here: https://shadow-cljs.github.io/docs/UsersGuide.html#deps-edn
they do not mix. so everything goes into deps.edn with or without aliases