← Home

Babashka `bb` and Not Babashka `nbb`

29 August, 2024

bb

Babashka Home, Github.

Babashka is a native Clojure interpreter for scripting with fast startup. Its main goal is to leverage Clojure in places where you would be using bash otherwise.

TLDR;

bb -e '(+ 1 20)'
bb -e '(-> (org.httpkit.client/get "https://datafy.id") deref :status)'
bb tasks

cat <<EOF > bb.edn
{:tasks {hello (println "hello there")}}
EOF

bb hello # run the task named hello

nbb

Not Babashka. Node.js Babashka!? nbb is bb atop JS runtime, e.g. bun or nodejs.

Home, Api Doc.

Getting Started

# Using bun, this will automatically download nbb if necessary
# and compute bcrypt hash of given password
bunx --bun nbb -e '(js/Bun.password.hash "pass" #js {:algorithm "bcrypt"})'

We can make it more organized by creating config file nbb.edn and create a cljs file.

mkdir x && cd x
touch nbb.edn
touch hello.cljs

Config file nbb.edn could be as simple as this:

{:paths ["."]}

And the hello.cljs content, for example shown here, we will use bun hash api.

(ns hello)

(defn greeting [& {:keys [to]}]
  (println (str "Hello " to)))

(defn -main [& [password]]
  ;; note that if we return promise, it will be automatically waited
  ;; and then result is printed
  (js/Bun.password.hash password #js {:algorithm "bcrypt"}))

(defn bcrypt [& {:keys [password]
                 :or {password "pass"}}]
  (-> (js/Bun.password.hash password #js {:algorithm "bcrypt"})
      (.then (fn [x]
               {:password password
                :hash x}))))

With these two files, now we could execute the script with nbb like this:

bunx --bun nbb -x hello/greeting --to "Ridho"
bunx --bun nbb -x hello/bcrypt --password your_strong_password
bunx --bun nbb -x hello/bcrypt :password "your_strong_password" # same like above
bunx --bun nbb -m hello your_strong_password

nbb Api

See latest api doc here.

Builtin NS: clojure.core, clojure.set, clojure.edn, clojure.string, clojure.walk, clojure.data, clojure.test and clojure.pprint.

nbb.core: *file*, load-file, load-string, slurp, time.

nbb.repl: repl, socket-repl.

nbb.error: print-error-report.

babashka.cli: auto-coerce, coerce, dispatch, format-opts, format-table, merge-opts, number-char?, opts->table, pad, pad-cells, parse-args, parse-cmds, parse-keyword, parse-keyword, rows, spec->opts.

promesa.core: *loop-run-fn*, ->, ->>, TimeoutException, all, any, as->, bind, cancel!, cancelled?, catch, catch', chain, chain', create, deferred, deferred?, delay, do, do!, done?, err, error, finally, future, handle, let, loop, map, mapcat, pending?, plet, promise, promise?, promisify, race, recur, reject!, rejected, rejected?, resolve!, resolved, resolved?, run!, then, then', thenable?, timeout, with-redefs, wrap.

reagent.core: atom, as-element, with-let, cursor, create-class, create-compiler.

reagent.ratom: with-let-values, reactive?.

reagent.dom.server: render-to-string, render-to-static-markup.

applied-science.js-interop: get, get-in, contains?, select-keys, lookup, assoc!, assoc-in!, update!, extend!, push!, unshift!, call, apply, call-in, apply-in, obj, let, fn, defn, lit.

clojure.tools.cli: format-lines, summarize, get-default-options, parse-opts, make-summary-part.

cognitect.transit: write, writer, write-handler, write-meta, read, read, read-handler, tagged-value.

cljs-bean.core: bean, bean?, object, ->js, ->clj.