nbb

Gregory Bleiker 2025-04-25T16:04:18.304109Z

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" ))

borkdude 2025-05-08T12:07:55.547509Z

@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.cljs

borkdude 2025-05-08T12:08:01.252169Z

can you verify?

borkdude 2025-05-08T12:10:23.501899Z

the bundle command doesn't work yet, this just assumes npm/node, not deno, but I can take a look at this later

❀️ 1
Gregory Bleiker 2025-05-08T12:10:37.403499Z

@borkdude will do asap, won't be before this evening though, I'm afraid

borkdude 2025-05-08T12:14:14.533619Z

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)

borkdude 2025-05-08T12:14:27.762269Z

you need to manually load react though, this doesn't work without it

borkdude 2025-05-08T12:14:34.349549Z

since reagent must find react somewhere

Gregory Bleiker 2025-05-08T12:15:21.931689Z

what du you mean with "manually"? put it in deno.json, for example? or just the require part?

borkdude 2025-05-08T12:15:36.332549Z

include ["npm:react"] in the require part

borkdude 2025-05-08T12:15:48.868209Z

just once somewhere in your app

Gregory Bleiker 2025-05-08T12:15:52.861629Z

if that's all that's needed that is ace!

borkdude 2025-05-08T12:15:57.208989Z

before reagent is loaded

Gregory Bleiker 2025-05-08T12:31:53.940939Z

@borkdude can confirm above is working (couldn't wait)

Gregory Bleiker 2025-05-08T12:53:19.145959Z

(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)                                               
                                                                                                                                     

Gregory Bleiker 2025-05-08T12:53:47.612789Z

is this the way to include reagent.dom?

borkdude 2025-05-08T12:55:09.547059Z

yes, but obviously something is wrong here, I'll take a look

Gregory Bleiker 2025-05-08T12:55:27.638709Z

sorry for being such a pain

borkdude 2025-05-08T12:55:45.609639Z

not at all, it's a nice challenge to make this work ;)

πŸ’ͺ 1
borkdude 2025-05-08T13:31:38.925789Z

it's unclear to me if react-dom server should be loaded with: "npm:react-dom/server" or "npm:react-dom-server"

borkdude 2025-05-08T13:33:37.096049Z

ok, apparently "npm:react-dom/server"

Gregory Bleiker 2025-05-08T13:35:35.117419Z

hm, that gives me an error though

Gregory Bleiker 2025-05-08T13:35:53.623709Z

also, it would be very un-npm-y, or not?

borkdude 2025-05-08T13:36:35.146379Z

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);

borkdude 2025-05-08T13:37:24.452449Z

I'm getting locally:

Type:     TypeError
Message:  Could not resolve 'npm:react-dom@17.0.2/server'

Gregory Bleiker 2025-05-08T13:45:58.425619Z

the script above is tsx, correct?

borkdude 2025-05-08T13:48:06.545099Z

yes

borkdude 2025-05-08T13:55:28.369899Z

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)

borkdude 2025-05-08T13:57:37.778589Z

change to (.html ...) if you want to render the HTML to HTML

Gregory Bleiker 2025-05-08T14:01:08.706259Z

A small response for a webserver... but a giant leap for an app :)

πŸŽ‰ 1
Gregory Bleiker 2025-05-08T14:01:25.711789Z

excellent

Gregory Bleiker 2025-05-08T14:01:36.125469Z

I'll unpublish my stuff on jsr

borkdude 2025-05-08T14:32:00.725669Z

somehow deno prefers the react version that is a dev dependency of nbb

borkdude 2025-05-08T14:40:22.137369Z

hmm, weird, now this just works:

["npm:react"]
            ["npm:react-dom/server"]

borkdude 2025-05-08T14:41:12.573489Z

I think as long as I don't use the local cli.js things are fine, it just prefers the local dependencies

Gregory Bleiker 2025-05-08T15:45:28.470739Z

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

Gregory Bleiker 2025-05-04T17:57:01.234309Z

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?

borkdude 2025-05-04T19:00:16.194639Z

That’s how I’d do it. Sorry I didn’t have time to look at this yet

Gregory Bleiker 2025-05-04T19:58:46.914679Z

no worries. Some things are working. I'd really like reagent integration, no luck so far

Gregory Bleiker 2025-05-01T11:59:05.357499Z

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.

borkdude 2025-05-01T12:00:22.363879Z

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?

Gregory Bleiker 2025-05-01T12:14:03.567129Z

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

borkdude 2025-05-01T12:15:06.519749Z

should be easy to repro I think as a smaller example, by using node readFileSync?

Gregory Bleiker 2025-05-01T12:15:32.426399Z

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???

borkdude 2025-05-01T12:15:50.388629Z

it calls out to #babashka to do so

borkdude 2025-05-01T12:15:59.850019Z

it's kind of a hack

Gregory Bleiker 2025-05-01T12:18:16.308529Z

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?

borkdude 2025-05-01T12:18:49.275789Z

if they are used in an import, and you're using deno, I guess so

borkdude 2025-05-01T12:19:01.099899Z

not exactly in which scenario

borkdude 2025-05-01T12:19:05.116149Z

sure

borkdude 2025-05-01T12:19:26.992069Z

if they are loaded only internally, then you don't have to expose them

Gregory Bleiker 2025-05-01T12:20:27.446419Z

are things from nbb_bundler.js ever used outside (do you know)?

borkdude 2025-05-01T12:21:31.903549Z

should not be, it's just a tool that produces a single file

borkdude 2025-05-01T14:55:28.346349Z

hopefully I have some time to look into this tomorrow

borkdude 2025-04-25T16:11:27.205239Z

It’s done using dynamic import

borkdude 2025-04-25T16:31:58.703439Z

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

borkdude 2025-04-25T16:32:08.440429Z

but I had to give it explicit access

borkdude 2025-04-25T16:32:41.453339Z

hope that makes sense?

borkdude 2025-04-25T20:39:30.066179Z

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 on

Gregory Bleiker 2025-04-25T22:03:31.366809Z

Sorry, was afk. Will do.

Gregory Bleiker 2025-05-05T12:32:33.926559Z

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.

πŸ‘ 1
Gregory Bleiker 2025-04-28T07:05:51.196109Z

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

borkdude 2025-04-28T07:35:54.502619Z

and perhaps the npm compatibility that jsr described?

borkdude 2025-04-28T07:36:06.286019Z

I'll get back to this later btw, I have to do other stuff today and tomorrow

Gregory Bleiker 2025-04-28T07:36:57.525469Z

Thanks again for picking this up so quickly!

Gregory Bleiker 2025-04-28T07:37:25.657599Z

I have the day off, so I'm trying to piece together the sample above

borkdude 2025-04-28T07:37:56.624299Z

if you have time and want to move this forward, perhaps you can research how to make a jsr package from nbb :)

πŸ‘ 1
Gregory Bleiker 2025-04-28T12:31:25.701049Z

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

Gregory Bleiker 2025-04-28T12:32:17.323629Z

I will revoke (hope I can!) the jsr package as soon as it's not needed any more

Gregory Bleiker 2025-04-28T12:35:09.733809Z

also, `deno -A jsr:@gregb/jsr-nbb-tryout deno_import.cljs aTestString` with direct import is working

borkdude 2025-04-28T12:35:18.647209Z

thanks :) I'll have a look in a few days. so the jsr import is working?

πŸ‘ 1
Gregory Bleiker 2025-04-28T12:36:37.651199Z

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

Gregory Bleiker 2025-04-27T16:01:43.801069Z

I put in this: https://github.com/babashka/nbb/issues/379 Could it be something to do with the import being async (await import...)?

borkdude 2025-04-27T16:03:26.278969Z

I'll have a quick look

❀️ 1
borkdude 2025-04-27T16:03:31.103659Z

never really tested with deno

Gregory Bleiker 2025-04-27T16:04:33.341799Z

I haven't looked at deno too much either, but I really like the no node_modules

borkdude 2025-04-27T16:21:07.693689Z

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.

Gregory Bleiker 2025-04-27T16:32:43.909159Z

Hard to say if it's worth the effort. I'd find it wicked if it worked, though.

Gregory Bleiker 2025-04-27T16:35:20.394309Z

Is it possible to directly call the deno import through nbb,like 'js/await js/import' or similar?

borkdude 2025-04-27T16:38:26.821039Z

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.

borkdude 2025-04-27T16:38:41.352079Z

so I think it can be fixed. need some more time, I have to make dinner for my wife now, it's my turn :)

borkdude 2025-04-27T16:39:47.380459Z

you can make a working js-import like this:

(def my-import (js/eval "(s) => import(s)")
and then use that

Gregory Bleiker 2025-04-27T16:40:09.786259Z

Same here, really appreciate the effort! But don't keep your wife waiting!

borkdude 2025-04-27T18:48:56.204709Z

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"

borkdude 2025-04-27T18:54:12.019409Z

Got the REPL working in deno as well:

$ deno run -A ./cli.js
Welcome to nbb v1.3.196!
user=> (+ 1 2 3)
6

borkdude 2025-04-27T18:54:50.356769Z

user=> (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"

Gregory Bleiker 2025-04-27T18:57:02.187319Z

This is in the dev branch?

borkdude 2025-04-27T19:00:47.802789Z

yes, now pushed it to the dev branch

πŸ‘ 1
borkdude 2025-04-27T19:11:53.010759Z

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 πŸ˜‚

borkdude 2025-04-27T19:19:14.401469Z

fixed

Gregory Bleiker 2025-04-27T19:25:02.362779Z

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: ?

borkdude 2025-04-27T19:31:56.862849Z

it's a node convention since node 14

borkdude 2025-04-27T19:32:09.067369Z

almost all of the tests are passing in deno itself now too

borkdude 2025-04-27T19:32:43.627949Z

if the tests keep working like this, I'll just go ahead and merge this

πŸŽ‰ 1
borkdude 2025-04-27T19:36:50.253329Z

btw I have no idea what jsr: is but I'm happy it works :)

Gregory Bleiker 2025-04-27T19:39:32.805579Z

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

borkdude 2025-04-27T19:40:34.248909Z

do you expect to import with the jsr prefix or without it?

borkdude 2025-04-27T19:41:45.801529Z

I haven't tested what happens when you do jsr add and then without the prefix

Gregory Bleiker 2025-04-27T19:42:37.986129Z

I would think it should be the same as with deno...https://docs.deno.com/runtime/fundamentals/modules/

Gregory Bleiker 2025-04-27T19:42:48.302019Z

So with prefix

borkdude 2025-04-27T19:42:59.550739Z

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"])
nil

borkdude 2025-04-27T19:43:01.226879Z

cool

Gregory Bleiker 2025-04-27T19:44:16.005029Z

Then you have a deno.json now which is used?

borkdude 2025-04-27T19:57:47.675909Z

yeah a deno.lock apparently

borkdude 2025-04-27T21:01:39.824149Z

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 out

borkdude 2025-04-27T21:27:37.936799Z

I guess it's this issue: https://github.com/denoland/deno/issues/24935

borkdude 2025-04-27T21:32:29.780129Z

so I'll probably have to publish nbb to jsr first to get this to work

Gregory Bleiker 2025-04-28T06:22:07.862529Z

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?

borkdude 2025-04-28T06:22:50.715279Z

> 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

borkdude 2025-04-28T06:23:35.303129Z

I could just try to publish to jsr, but have to figure out how to do that

Gregory Bleiker 2025-04-28T06:25:14.598069Z

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

borkdude 2025-04-28T06:26:00.323889Z

the import happens in a function that is part of the nbb npm package, this is why it complains

Gregory Bleiker 2025-04-28T06:26:01.266659Z

publishing to jsr would be beneficial in any case, though

Gregory Bleiker 2025-04-28T06:29:04.548929Z

according to the https://jsr.io/docs/publishing-packages, it should be as simple as deno publish, but it never is, is it? πŸ˜‰

borkdude 2025-04-28T06:29:32.347279Z

no, you need to make a deno.json or jsr.json file with "exports"

borkdude 2025-04-28T06:29:50.167289Z

and I didn't see how to expose a "bin" or "main" binary script using that

borkdude 2025-04-28T06:30:12.080539Z

I hope it's not index.mjs since I've designated index.mjs to import nbb's programmatic API

borkdude 2025-04-28T06:30:33.683109Z

although I guess I could control that via the exports

πŸ‘ 1
borkdude 2025-04-28T06:31:27.183989Z

perhaps this works: https://github.com/jsr-io/jsr-npm

Gregory Bleiker 2025-04-28T06:32:09.770169Z

also, I didn't see this before: https://jsr.io/docs/npm-compatibility

Gregory Bleiker 2025-04-28T06:33:11.570539Z

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)

borkdude 2025-04-28T06:34:13.473239Z

oak is only on jsr, is that your problem?

Gregory Bleiker 2025-04-28T06:34:29.164719Z

yes, it's a deno thing

Gregory Bleiker 2025-04-28T06:34:57.997199Z

or maybe not?

borkdude 2025-04-28T06:35:00.876429Z

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

πŸ‘ 1
Gregory Bleiker 2025-04-28T06:35:15.982659Z

I actually didn't even check...

Gregory Bleiker 2025-04-28T06:47:04.430439Z

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.cljs

Gregory Bleiker 2025-04-28T06:47:19.146949Z

it actually still looks the same as before...

borkdude 2025-04-28T06:47:57.129129Z

You are still using version 196

Gregory Bleiker 2025-04-28T06:49:03.530929Z

ah, with 200 it's the same