SCI, similar to babashka • Developed since September 2021 • Can be used to script against any library in Node.js ecosystem, including ES6 • Included CLJS libraries: promesa, js-interop, reagent, ... $ npx nbb user=> (require '["child_process" :as cp]) nil user=> (str (cp/execSync "echo dude")) "dude\n" user=> (require '[applied-science.js-interop :as j]) nil user=> (j/get-in (clj->js {:a {:b {:c :foo}}}) [:a :b :c]) "foo"
Node.js • time nbb -e '(+ 1 2 3)' => ~120-180ms (could be reduced by eliding docstrings, etc.) • Uses Node.js version from system (14+ recommended) • ES6 modules support • Currently actively developed and maintained
No, complementary. • Does nbb mean bb is less actively developed? > No. Both based on SCI, bene fi t from shared code-base. • Use case for nbb > bb: "Does bb have a library / pod for ...?" • Parsing excel sheets? • Parsing iCal fi les? • > Not currently, but nbbjs + a Node.js library might do the trick!
APIs tend to become more promise-based than callback based • Doable via raw JS interop • But there's an awesome library with convenient macros/ functions which makes it easier: promesa • Built-in to nbb: "the way" to deal with promises
user=> (range) ^C"Error: Script execution was interrupted by `SIGINT`" • Uses Node VM which can be killed with SIGINT • Technique could also be applied to nREPL server
library (shadow-cljs convention adopted by nbb): (require '["fs" :as fs]) (ns example (:require ["asciidoctor$default" :as asciidoctor])) • Implemented using dynamic import: (js/import ...) to support ES module s • Which means that ns and require must be asyn c • Which means all (top level) eval must be async
synchronou s • Solution: nbb reads every top level expression + custom eva l • If expression matches (ns ...): - eval every :require clause manually - if string lib name, use async js/import - built-in namespaces (reagent.core, promesa.core, ...) are loaded lazily, async for better startup tim e • SCI's clojure.core/require is patched to use an async variant, wrapped in nbb.core/await • Every other expression is evaluated synchronously and wrapped in promis e • All top level expressions are now evaluated as chained promise
compiler only emits CJS for Node.js • Shadow-cljs to the rescue: :target :esm • nbb is available as library from JS as ESM: import { loadFile } from nbb