# Atomsync A Clojure-native synced atom. Offline-first key-value store with an `atom` interface that syncs to a SQLite-backed server over Transit. ```clojure (def conn ( {"todo:1" {:text "Buy milk" :tags #{:groceries}}} ``` ## What it does - **Preserves Clojure types**: keywords, sets, UUIDs, instants — no lossy JSON - **Works offline**: reads/writes hit IndexedDB immediately, syncs when online - **Atom interface**: `swap!`, `deref`, `add-watch` — works with Reagent, Rum, or raw CLJS - **~500 lines**: client (~300) + server (~200), no opaque dependencies ## Quick start ### Server ```bash clj -M:server # or: clj -M:server 8090 my-data.db ``` Starts on `http://localhost:8090` with a SQLite file at `atomsync.db`. ### Client (CLJS) ```clojure (ns my-app.core (:require [atomsync.core :as pb] [cljs.core.async :refer [go ` — returns changed docs - **Push**: `POST /sync` — sends local changes with version numbers - **Conflicts**: server rejects stale writes, client accepts server value ## Auth Optional token-based auth: ```clojure (server/start! {:port 8090 :users {"alice" {:token "abc123" :groups #{"todo" "settings"}} "bob" {:token "def456" :groups #{"todo"}}}}) ``` Client passes token: ```clojure (pb/synced-atom conn "todo" {:server "http://localhost:8090/sync" :token "abc123"}) ``` ## Dependencies | Layer | Library | Purpose | |--------|---------|---------| | Server | next.jdbc + sqlite-jdbc | SQLite storage | | Server | nippy | Binary serialization | | Server | transit-clj | Wire format | | Server | http-kit | HTTP server | | Client | transit-cljs | Serialization (IDB + wire) | | Client | core.async | Sync coordination | ## Tests ```bash # All server tests clj -M:dev -e '(require (quote atomsync.db-test) (quote atomsync.transit-test) (quote atomsync.server-test) (quote atomsync.auth-test)) (clojure.test/run-all-tests #"atomsync\..*")' ``` ## License MIT