Skip to content

cormacc/cljserial

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CLJSerial example

Table of Contents

Overview

A my-first-cljs-project implementing the following completely unrelated functions:

  • A webserial terminal (implemented using the clj-statecharts library)
  • A persistent bi-temporal database in the browser using datascript backed by indexedDB for transaction log storage
  • local file storage using OPFS (the Origin Private File System)

It includes shadow-cljs builds demonstrating the above using two different frontend libraries/approaches:

  • Replicant (+ portfolio for component-driven development)
  • re-frame (with Uix2)

The replicant build includes a janky time-travelling TODO mvc view demoing the bi-temporal datascript implementation, and a similarly nasty page allowing files to be created and viewed.

The re-frame example has bits of integration with supabase in varying states of repair, but this hasn’t been a recent focus

The OPFS file storage implementation uses a metadata index stored in indexedDB. This is fairly redundant as yet, but the additional metadata will be useful for a future sync implementation to S3 or whatever.pp

In both the re-frame and replicant examples, the persistent datascript domain database is embedded in the app view db/atom. Idea being that we differentiate between transient/disposable view data and more durable domain data that we want to persist and for which we want a strong audit trail (hence transaction log).

All this stuff is playground/POC level — immature and not thoroughly tested.

Quickstart

This repo includes three app entry points:

./src/stack/examples/replicant/app.cljs
The replicant example app
./src/stack/examples/re_frame/app.cljs
The re-frame example app
./src/cljserial/app.cljs
The development app

The last of these just duplicates the replicant example for now. It’s intended to diverge – I find it useful to keep general purpose / re-usable code in the `stack` namespace and app/domain specifics in their own namespace.

It also includes unit test, css and portfolio (component driven development) builds/watches.

Other relevant entry points....

Launch the replicant example

bb watch:replicant

This will serve the following:

Example app
http://localhost:8084
Portfolio
http://localhost:8082
Unit test runner
http://localhost:8081

Launch the re-frame/uix example

bb watch:re-frame

This will serve the following:

Examples app
http://localhost:8083
Unit test runner
http://localhost:8081

Launch the development app

bb watch:local

This will serve the following:

App
http://localhost:8080
Portfolio
http://localhost:8082
Unit test runner
http://localhost:8081

Other build targets

Babashka tasks

bb tasks

watch:local Run app (port 8080) with local dockerised supabase (test and portfolio builds enabled). watch:cloud Run app (port 8080) with cloud-hosted supabase (test and portfolio builds enabled). watch:replicant Run replicant (port 8084) with local dockerised supabase (test and portfolio builds enabled). watch:re-frame Run examples (port 8083) with local dockerised supabase (test and portfolio builds enabled). watch:css Tailwind watch task watch:postcss Tailwind watch task watch:portfolio Run portfolio component-driven test UI on http://localhost:8082 watch:test Run frontend unit test runner on http://localhost:8081 build:release Build release version of the app. build:pages Compile static version of the app for upload to gitlab pages. sb:start sb:stop sb:edn Extract environment for local dockerised supabase to edn. tailwind:edn Extract list of DaisyUI themes included via tailwind config for use in UI theme selector.

UI dev/debug tooling

The app targets include both re-frame-10x (at the right of the app window) and cljs-react-devtools (at the foot) To show/hide the re-frame-10x panel, use Ctrl+Shift+x. To show/hide the cljs-react-dev-tools panel, use Ctrl+Shift+Meta+R.

shadow-cljs inspect

shadow-cljs includes a browser based interface allowing the runtime (function defs and data) to be inspected and modified – effectively a GUI for the REPL. Accessible at http://localhost:9630

re-frame-10x

Very useful dev tooling for re-frame. Shows up as a sidebar for the dev build. Show/hide using Ctrl-Shift-x. See https://github.com/day8/re-frame-10x for further info.

flow-storm debugger

This includes some quick and dirty wiring for the excellent flow-storm debugger. The provided nix flake also installs the required dependencies. Babashka tasks have been added to launch the debugger for each of the build targets. Start your watch as usual with bb watch:replicant or whatever, then in another window, bb flow:replicant.

There are definitely more ergonomic ways to wire it in and launch it (thinking particularly in the context of doing a release build without flowstorm), but this is as far as I’ve gotten…

Language/library references

(Don’t judge me, I’m a C programmer)

Clojure style guide
Wot it says on the tin....
from bash to babashka
Useful blog post, pointing at some handy FS-related libraries embedded in babashka

Getting up and running

Browser console logging

Pretty console logging requires custom formatters to have been enabled for your browser dev tools window – see: https://github.com/binaryage/cljs-devtools/blob/master/docs/installation.md

Without this config, the log entries will contain lots of less useful js data structure.

Backend infrastructure options

All of the core functionality in this initial prototype is suitable for deployment as a static site without additional backend infrastructure. However this repository is a testbed for a project that will need auth, storage etc., and to that end we’ve been kicking the tires of a couple of options there. Initial work was with AWS (some historic info retained in a subsection below), but since switched to supabase for a number of reasons:

Offline-first development workflow
Supabase CLI makes it very easy to stand up a complete local development environment in Docker containers.
Portability
Supabase provide PAAS subscriptions, however also allow you to self-host elsewhere.
Ease of use
Supabase is a more tightly integrated product than the extensive AWS ecosystem of services, which should reduce the complexity / cognitive overload potential for a relatively small dev team.

Essential commands

supabase start
supabase status
supabase stop

When running in docker, open the supabase UI at http://localhost:54323 Detailed notes can be found here: ./supabase.org

Historic notes on AWS integration can be found here:

Webserial / web bluetooth considerations

Browser API compatibility

As of Feb 2025, the Web Serial and Web Bluetooth APIs are supported only on chrome/chromium, edge and opera. See the Mozilla Developer Network pages on Web Bluetooth and Web Serial for more info.

On chrome/chromium use of the web bluetooth API requires a couple of optional flags to be enabled as follows

  • Enter ‘chrome://flags’ in the URL bar
  • Type ‘web bluetooth’ in the search field
  • Ensure the following options are all enabled:
    • Web Bluetooth
    • Use the new permissions backend for Web Bluetooth
    • Web Bluetooth confirm pairing support

Port access on linux

N.B. On linux (well, Arch derivatives anyway), access to Bluetooth and serial port services as an privileged user require you to be a member of the ‘lp’ and ‘uucp’ groups, respectively. To set this, enter the following command in your terminal:

sudo usermod -aG lp,uucp <your-username>

You’ll need to logout and login again for the new membership privileges to take effect.

Port availability / power saving

In addition, many distributions (including Manjaro) install laptop-mode-tools by default, putting certain USB devices to sleep when running on battery power.

To disable this for the legacy MBT CD, you need to add the USB device ID for its integral FTDI module to a blacklist.

In /etc/laptop-mode/conf.d/runtime-pm.conf, locate the line beginning AUTOSUSPEND_RUNTIME_DEVID_BLACKLIST and amend it to include 0403:6015 (the USB device ID for the FTDI module).

AUTOSUSPEND_RUNTIME_DEVID_BLACKLIST="0403:6015"

Similar measures may be required for the USB interface to the MBX CD hardware.

See the Laptop Mode Tools section of the Arch linux WIKI for further information.

Build cheatsheet

Dependencies

The majority of these are handled by via:

In addition, fontawesome is required at build time to unpack svg for icons. This can be downloaded into your source tree by executing the snippet below (from https://github.com/cjohansen/fontawesome-clj):

clojure -Sdeps "{:deps {no.cjohansen/fontawesome-clj {:mvn/version \"2024.01.22\"} \
                      clj-http/clj-http {:mvn/version \"3.12.3\"} \
                      hickory/hickory {:mvn/version \"0.7.1\"}}}" \
-M -m fontawesome.import :download resources 6.4.2

Repl cheatsheet

See https://shadow-cljs.github.io/docs/UsersGuide.html#_clojurescript_repl

Open a repl session from a shell

To open a repl session from a shell prompt

npx shadow-cljs cljs-repl app

Open a repl session from your editor

Currently using Emacs/Cider. The docs provided for cider are excellent. Read them.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published