Another deno question: How are modules resolved with nbb? For instance, is something like this possible? Or are npm packages mandatory?
(ns test (:require ["jsr:@luca/cases@1.0.0" :as cc]))
(print (cc/camelCase "test string" ))@gregorybleiker This script now works:
(ns script
(:require
["npm:react@18.3.1"]
["npm:ink@5.2.1" :refer [render]]
["npm:ink-select-input$default" :as SelectInput]
[reagent.core :as r]))
(def items (clj->js [{:label "First"
:value "first"}
{:label "Second"
:value "second"}]))
(declare ink-state)
(defn handle-select [i]
((.-clear ink-state))
((.-unmount ink-state))
(js/console.log i)
(js/process.exit 0))
(defn select []
[:> SelectInput {:items items :onSelect handle-select}])
(js/console.log render)
(def ink-state (render (r/as-element [select])))
with
deno run -A jsr:@babashka/nbb@1.3.200-test-3 /tmp/script.cljscan you verify?
the bundle command doesn't work yet, this just assumes npm/node, not deno, but I can take a look at this later
@borkdude will do asap, won't be before this evening though, I'm afraid
This sample script form your repo also works:
(ns main
(:require ["jsr:@hono/hono" :as h]
["npm:react"]
[reagent.core :as r]))
(defonce state (r/atom 0))
(def app (new h/Hono))
(.get
app
"/"
(fn [ctx]
(.text ctx "Hello Hono!")))
(js/Deno.serve app.fetch)you need to manually load react though, this doesn't work without it
since reagent must find react somewhere
what du you mean with "manually"? put it in deno.json, for example? or just the require part?
include ["npm:react"] in the require part
just once somewhere in your app
if that's all that's needed that is ace!
before reagent is loaded
@borkdude can confirm above is working (couldn't wait)
(ns main
(:require ["jsr:@hono/hono" :as h]
["npm:react"]
["npm:react-dom"]
[reagent.core :as r]
[reagent.dom.server :refer [render-to-string]]))
(defonce state (r/atom 0))
(def app (new h/Hono))
(.get
app
"/"
(fn [ctx]
(.text ctx (render-to-string [:div [:p "Hello"]])
)))
(js/Deno.serve app.fetch)
is this the way to include reagent.dom?
yes, but obviously something is wrong here, I'll take a look
sorry for being such a pain
not at all, it's a nice challenge to make this work ;)
it's unclear to me if react-dom server should be loaded with: "npm:react-dom/server" or "npm:react-dom-server"
ok, apparently "npm:react-dom/server"
hm, that gives me an error though
also, it would be very un-npm-y, or not?
it does work for this script:
import React from "npm:react";
import ReactDOMServer from "npm:react-dom/server";
// A simple React component
function HelloWorld() {
return <h1>Hello from React and Deno!</h1>;
}
// Render the component to a string
const html = ReactDOMServer.renderToString(<HelloWorld />);
// Output the rendered HTML
console.log(html);I'm getting locally:
Type: TypeError
Message: Could not resolve 'npm:react-dom@17.0.2/server'the script above is tsx, correct?
yes
This works now with test-5:
(ns main
(:require ["npm:react@19.1.0"]
["npm:react-dom@19.1.0/server"]
["jsr:@hono/hono" :as h]
[reagent.core :as r]
[reagent.dom.server :refer [render-to-string]]))
(defonce state (r/atom 0))
(def app (new h/Hono))
(.get
app
"/"
(fn [ctx]
(.text ctx (render-to-string [:div [:p "Hello"]])
)))
(js/Deno.serve app.fetch)change to (.html ...) if you want to render the HTML to HTML
A small response for a webserver... but a giant leap for an app :)
excellent
I'll unpublish my stuff on jsr
somehow deno prefers the react version that is a dev dependency of nbb
hmm, weird, now this just works:
["npm:react"]
["npm:react-dom/server"]I think as long as I don't use the local cli.js things are fine, it just prefers the local dependencies
yes, very strange. The whole packaging in deno is still very new to me. I listened to a podcast with Ryan Dahl and he says that the npm interaction is very complicated to develop
I'm still pretty stuck trying to get nbb to work fully with deno. I can get basic scripts to run (ones that don't import anything). As soon as I try to require things, an exception is thrown:
~/projects/clojure/nbb/my-app> deno --unstable-detect-cjs -A ~/projects/nbb/lib/nbb_main.js main.cljs
----- Error --------------------------------------
Type: TypeError
Message: (intermediate value)(intermediate value)(intermediate value).catch is not a function
error: Uncaught (in promise) Error: (intermediate value)(intermediate value)(intermediate value).catch is not a function
at file:///home/greg/projects/nbb/lib/nbb_main.js:13:196
at eventLoopTick (ext:core/01_core.js:178:7)
My current approach is to use bundle to see what is produced on the js side, but that doesn't seem to be what's happening when a file is invoked directly. @borkdude do you have any guidance on how to debug nbb? Insert print statements in the nbb code?Thatβs how Iβd do it. Sorry I didnβt have time to look at this yet
no worries. Some things are working. I'd really like reagent integration, no luck so far
I've been having mixed results so far. Just using deno libs with jsr seems to work ok, but everything else is breaking, for instance I can't get reagent working (because react is not found) and when I export stuff from the bundler then nbb stops working all together with an exception.
reagent + react is a special combination in nbb so that might be expected (could be solved, but I haven't looked into it) what exception do you get from the bundler?
deno --unstable-detect-cjs --unstable-sloppy-imports -A jsr:@gregb/jsr-nbb-tryout@0.0.5 sample1.cljs error: Uncaught (in promise) Error: EISDIR: illegal operation on a directory, open at node_internal_captureLargerStackTrace (ext:deno_node/internal/errors.ts:93:9) at node_internal_uvException (ext:deno_node/internal/errors.ts:186:10) at denoErrorToNodeError (ext:deno_node/internal/errors.ts:1898:14) at Module.readFileSync (ext:deno_node/fs/fs_readFile.ts:67:13) at https://jsr.io/@gregb/jsr-nbb-tryout/0.0.5/lib/nbb_bundler.js:14:51 at https://jsr.io/@gregb/jsr-nbb-tryout/0.0.5/lib/nbb_bundler.js:17:212
should be easy to repro I think as a smaller example, by using node readFileSync?
the whole packaging in nbb is black magic to me... for instance, how is it possible that you can pull clojure dependencies in with nbb.deps???
it calls out to #babashka to do so
it's kind of a hack
I have to do more debugging why it's not working even in the trivial case. From all the files produces in bb release in the lib folder, do I really need to export all of them?
if they are used in an import, and you're using deno, I guess so
not exactly in which scenario
sure
if they are loaded only internally, then you don't have to expose them
are things from nbb_bundler.js ever used outside (do you know)?
should not be, it's just a tool that produces a single file
hopefully I have some time to look into this tomorrow
Itβs done using dynamic import
so similar to:
$ deno repl
Deno 1.44.4
exit using ctrl+d, ctrl+c, or close()
> import("jsr:@luca/cases@1.0.0")
β
Granted net access to "".
Promise { <pending> }io/@luca/cases/meta.json but I had to give it explicit access
hope that makes sense?
I do notice that it doesn't work in nbb currently:
user=> (require '["jsr:@luca/cases@1.0.0" :as cases])
"Error: Cannot find module 'jsr:@luca/cases@1.0.0'\nRequire stack:\n- /Users/borkdude/dev/babashka/script.cljs"
Feel free to file an issue so we can see what's going onSorry, was afk. Will do.
Been doing some more trials.. https://github.com/gregorybleiker/nbb/blob/main/sample.cljs
I've tried exporting nbb_reagent through deno.json (which shouldn't be in .gitignore) but it's not picked up correctly. Need to have bit of a frustration break.
using pnpm install jsr:@luca/cases and (:require ["@luca/cases" :as cc]) does work btw. Only (small) downside: you have to use pnpm or yarn
and perhaps the npm compatibility that jsr described?
I'll get back to this later btw, I have to do other stuff today and tomorrow
Thanks again for picking this up so quickly!
I have the day off, so I'm trying to piece together the sample above
if you have time and want to move this forward, perhaps you can research how to make a jsr package from nbb :)
I put together some stuff, it's rather chaotic, I'm afraid. I'll have to postpone for a few days as well. But deno -A jsr:@gregb/jsr-nbb-tryout now starts nbb (yay) and the code is in https://github.com/gregorybleiker/nbb
I will revoke (hope I can!) the jsr package as soon as it's not needed any more
also, `deno -A jsr:@gregb/jsr-nbb-tryout deno_import.cljs aTestString` with direct import is working
thanks :) I'll have a look in a few days. so the jsr import is working?
I can also create a PR if you want so it's easier for you to check what I changed. But it's no where near to be a mergeable pr, I'm afraid
I put in this: https://github.com/babashka/nbb/issues/379 Could it be something to do with the import being async (await import...)?
I'll have a quick look
never really tested with deno
I haven't looked at deno too much either, but I really like the no node_modules
I must make quite a lot of changes to get nbb working with deno in development, but all of those changes should be compatible with node, such as giving library imports a node: prefix, not using js/process, but (:require ["node:process" :as process]) etc.
Hard to say if it's worth the effort. I'd find it wicked if it worked, though.
Is it possible to directly call the deno import through nbb,like 'js/await js/import' or similar?
I pushed the deno related changed to a branch called deno-dev and I can start it like this:
Run:
bb dev
in one console. In another:
deno run -A ./cli.js -e '(ns foo (:require ["jsr:@luca/cases@1.0.0" :as cases]))'
When I make some changed in load-js-module I do see that the module can be correctly loaded:
(-> (resolve libname)
(.catch
(fn [_]
(prn :dude _)
(.then (esm/dynamic-import libname) js/console.log)
#_((.-resolve (:require @ctx)) libname))))
$ deno run -A ./cli.js -e '(ns foo (:require ["jsr:@luca/cases@1.0.0" :as cases]))'
:dude #object[Error Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file and data are supported by the default ESM loader. Received protocol 'jsr:']
[Module: null prototype] {
camelCase: [Function: camelCase],
constantCase: [Function: constantCase],
kebabCase: [Function: kebabCase],
pascalCase: [Function: pascalCase],
snakeCase: [Function: snakeCase],
splitPieces: [Function: splitPieces],
titleCase: [Function: titleCase]
}
about js/import or js/require: yeah, but those are currently hacked by nbb to make use of current directory etc. not with deno in mind.so I think it can be fixed. need some more time, I have to make dinner for my wife now, it's my turn :)
you can make a working js-import like this:
(def my-import (js/eval "(s) => import(s)")
and then use thatSame here, really appreciate the effort! But don't keep your wife waiting!
Got this working now:
$ deno run -A ./cli.js -e '(ns foo (:require ["jsr:@luca/cases@1.0.0" :as cases])) (cases/camelCase "dude-foo")'
"dudeFoo"Got the REPL working in deno as well:
$ deno run -A ./cli.js
Welcome to nbb v1.3.196!
user=> (+ 1 2 3)
6user=> (require '["jsr:@luca/cases@1.0.0" :as cases])
nil
user=> (js/console.log cases)
[Module: null prototype] {
camelCase: [Function: camelCase],
constantCase: [Function: constantCase],
kebabCase: [Function: kebabCase],
pascalCase: [Function: pascalCase],
snakeCase: [Function: snakeCase],
splitPieces: [Function: splitPieces],
titleCase: [Function: titleCase]
}
nil
user=> (cases/camelCase "foo-bar")
"fooBar"This is in the dev branch?
yes, now pushed it to the dev branch
the nbb tests are failing though with what looks like an innocent change. https://github.com/babashka/nbb/compare/deno-dev?expand=1 the REPL tests get stuck into a console REPL... :) I think because arg parsing went wrong somehow, since when invoking with nbb with no args, it starts a REPL π
fixed
wouldn't this change break all the people's code that are using only node? because now the imports need to be prefixed by node: ?
it's a node convention since node 14
almost all of the tests are passing in deno itself now too
if the tests keep working like this, I'll just go ahead and merge this
btw I have no idea what jsr: is but I'm happy it works :)
Seems to be the new kid on the block because npm seems to be under-loved by MS... Ryan Dahl has given it his blessing, that is good enough for me
do you expect to import with the jsr prefix or without it?
I haven't tested what happens when you do jsr add and then without the prefix
I would think it should be the same as with deno...https://docs.deno.com/runtime/fundamentals/modules/
So with prefix
oh that seems to work after jsr add as well:
$ deno run -A ./cli.js
Welcome to nbb v1.3.196!
user=> (require '["@luca/cases"])
nilcool
Then you have a deno.json now which is used?
yeah a deno.lock apparently
I published a new nbb but the one published to npm doesn't seem to work:
$ deno run -A npm:nbb@1.3.198 /tmp/script.cljs
----- Error --------------------------------------
Type: TypeError
Message: [ERR_UNSUPPORTED_ESM_URL_SCHEME] Only file and data URLS are supported by the default ESM loader. Received protocol 'jsr'
error: Uncaught (in promise) Error: [ERR_UNSUPPORTED_ESM_URL_SCHEME] Only file and data URLS are supported by the default ESM loader. Received protocol 'jsr'
at file:///Users/borkdude/dev/nbb/node_modules/.deno/nbb@1.3.198/node_modules/nbb/lib/nbb_main.js:13:196
The one compiled locally even with advanced does work:
$ deno run -A ./cli.js /tmp/script.cljs
Not sure what's going on here... But I'll have to postpone this to tomorrow to find outI guess it's this issue: https://github.com/denoland/deno/issues/24935
so I'll probably have to publish nbb to jsr first to get this to work
what a bummer. Strange that it does work locally but not as npm package. I always thought that npm didn't do anything to the code, just package it. Shall I open an issue on deno with the use-case above?
> Strange that it does work locally but not as npm package. This is because it's not an npm package but a local project. When in npm, jsr isn't usable. See the above deno issue
I could just try to publish to jsr, but have to figure out how to do that
I read the issue you're referencing, but is that really what is happening here? Because the jsr reference isn't in an npm package. nbb is launched via npm and interprets the cljs, or not? So the actual import happens in the interpreted part, which itself is not an npm package
the import happens in a function that is part of the nbb npm package, this is why it complains
publishing to jsr would be beneficial in any case, though
according to the https://jsr.io/docs/publishing-packages, it should be as simple as deno publish, but it never is, is it? π
no, you need to make a deno.json or jsr.json file with "exports"
and I didn't see how to expose a "bin" or "main" binary script using that
I hope it's not index.mjs since I've designated index.mjs to import nbb's programmatic API
although I guess I could control that via the exports
perhaps this works: https://github.com/jsr-io/jsr-npm
also, I didn't see this before: https://jsr.io/docs/npm-compatibility
it's a bit less cool than directly importing in the cljs, but it would probably work for what I'm trying to do (run an oak server that serves datastar, using hiccup to generate the page)
oak is only on jsr, is that your problem?
yes, it's a deno thing
or maybe not?
ok, give that a try I'd say, but making jsr: work in nbb is a good goal nonetheless. please do use the latest nbb version to see if everything still works
I actually didn't even check...
for some reason my stack trace is different to @borkdude:
~/projects/clojure/nbb/hello-test> deno run -A npm:nbb@1.3.196 deno_import.cljs
----- Error --------------------------------------
Message: Cannot find module 'jsr:@luca/cases'
Require stack:
- /home/greg/projects/clojure/nbb/hello-test/deno_import.cljs
Cannot find module 'jsr:@luca/cases'
Require stack:
- /home/greg/projects/clojure/nbb/hello-test/deno_import.cljsit actually still looks the same as before...
You are still using version 196
ah, with 200 it's the same