refactor: rename library from pocketbook to atomsync

This commit is contained in:
Florian Schroedl
2026-04-16 20:18:45 +02:00
parent bcf7e03332
commit b68f97247a
20 changed files with 73 additions and 73 deletions

View File

@@ -1,4 +1,4 @@
# Pocketbook # Atomsync
Clojure/ClojureScript offline-first synced atom library backed by IndexedDB (CLJS) or SQLite (CLJ). Clojure/ClojureScript offline-first synced atom library backed by IndexedDB (CLJS) or SQLite (CLJ).
@@ -24,7 +24,7 @@ This project uses **promesa** (`funcool/promesa`) for all async operations. Do n
## Project structure ## Project structure
``` ```
src/pocketbook/ src/atomsync/
store.cljc — PStore protocol (promises) store.cljc — PStore protocol (promises)
store/memory.cljc — in-memory store (testing/JVM) store/memory.cljc — in-memory store (testing/JVM)
store/idb.cljs — IndexedDB store (browser) store/idb.cljs — IndexedDB store (browser)

View File

@@ -1,10 +1,10 @@
# Pocketbook # Atomsync
A Clojure-native synced atom. Offline-first key-value store with an `atom` interface that syncs to a SQLite-backed server over Transit. A Clojure-native synced atom. Offline-first key-value store with an `atom` interface that syncs to a SQLite-backed server over Transit.
```clojure ```clojure
(def conn (<! (pocketbook/open "my-app"))) (def conn (<! (atomsync/open "my-app")))
(def todos (pocketbook/synced-atom conn "todo" {:server "http://localhost:8090/sync"})) (def todos (atomsync/synced-atom conn "todo" {:server "http://localhost:8090/sync"}))
(swap! todos assoc "todo:1" {:text "Buy milk" :tags #{:groceries}}) (swap! todos assoc "todo:1" {:text "Buy milk" :tags #{:groceries}})
@todos ;=> {"todo:1" {:text "Buy milk" :tags #{:groceries}}} @todos ;=> {"todo:1" {:text "Buy milk" :tags #{:groceries}}}
@@ -26,13 +26,13 @@ clj -M:server
# or: clj -M:server 8090 my-data.db # or: clj -M:server 8090 my-data.db
``` ```
Starts on `http://localhost:8090` with a SQLite file at `pocketbook.db`. Starts on `http://localhost:8090` with a SQLite file at `atomsync.db`.
### Client (CLJS) ### Client (CLJS)
```clojure ```clojure
(ns my-app.core (ns my-app.core
(:require [pocketbook.core :as pb] (:require [atomsync.core :as pb]
[cljs.core.async :refer [go <!]])) [cljs.core.async :refer [go <!]]))
(go (go
@@ -94,7 +94,7 @@ Client passes token:
```bash ```bash
# All server tests # All server tests
clj -M:dev -e '(require (quote pocketbook.db-test) (quote pocketbook.transit-test) (quote pocketbook.server-test) (quote pocketbook.auth-test)) (clojure.test/run-all-tests #"pocketbook\..*")' 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 ## License

24
bb.edn
View File

@@ -1,5 +1,5 @@
{:tasks {:tasks
{server {:doc "Start the Pocketbook sync server (serves example app)" {server {:doc "Start the Atomsync sync server (serves example app)"
:task (shell "clj" "-M:server" "--static-dir" "example/todomvc")} :task (shell "clj" "-M:server" "--static-dir" "example/todomvc")}
cljs {:doc "Compile ClojureScript (one-shot)" cljs {:doc "Compile ClojureScript (one-shot)"
@@ -13,26 +13,26 @@
:task (shell "clj" "-M:cljs-dev")} :task (shell "clj" "-M:cljs-dev")}
test {:doc "Run all server tests" test {:doc "Run all server tests"
:task (let [expr (str "(require 'pocketbook.db-test 'pocketbook.transit-test" :task (let [expr (str "(require 'atomsync.db-test 'atomsync.transit-test"
" 'pocketbook.server-test 'pocketbook.core-test)" " 'atomsync.server-test 'atomsync.core-test)"
" (let [r (clojure.test/run-all-tests #\"pocketbook\\..*\")]" " (let [r (clojure.test/run-all-tests #\"atomsync\\..*\")]"
" (System/exit (if (and (zero? (:fail r)) (zero? (:error r))) 0 1)))")] " (System/exit (if (and (zero? (:fail r)) (zero? (:error r))) 0 1)))")]
(shell "clj" "-M:dev" "-e" expr))} (shell "clj" "-M:dev" "-e" expr))}
dev {:doc "Start server and CLJS watch in tmux" dev {:doc "Start server and CLJS watch in tmux"
:task (let [dir (System/getProperty "user.dir")] :task (let [dir (System/getProperty "user.dir")]
(shell {:dir dir} "tmux new-session -d -s pocketbook-dev -n server -c" dir) (shell {:dir dir} "tmux new-session -d -s atomsync-dev -n server -c" dir)
(shell {:dir dir} "tmux send-keys -t pocketbook-dev:server" "bb server" "Enter") (shell {:dir dir} "tmux send-keys -t atomsync-dev:server" "bb server" "Enter")
(shell {:dir dir} "tmux new-window -t pocketbook-dev -n cljs -c" dir) (shell {:dir dir} "tmux new-window -t atomsync-dev -n cljs -c" dir)
(shell {:dir dir} "tmux send-keys -t pocketbook-dev:cljs" "bb cljs:watch" "Enter") (shell {:dir dir} "tmux send-keys -t atomsync-dev:cljs" "bb cljs:watch" "Enter")
(println "🔶 tmux session 'pocketbook-dev' started") (println "🔶 tmux session 'atomsync-dev' started")
(println " App: http://localhost:8090") (println " App: http://localhost:8090")
(println " Server: http://localhost:8090/sync") (println " Server: http://localhost:8090/sync")
(println " Attach: tmux attach -t pocketbook-dev"))} (println " Attach: tmux attach -t atomsync-dev"))}
dev:stop {:doc "Stop the dev tmux session" dev:stop {:doc "Stop the dev tmux session"
:task (shell "tmux kill-session -t pocketbook-dev")} :task (shell "tmux kill-session -t atomsync-dev")}
dev:restart {:doc "Restart the dev tmux session" dev:restart {:doc "Restart the dev tmux session"
:task (do (shell {:continue true} "tmux kill-session -t pocketbook-dev") :task (do (shell {:continue true} "tmux kill-session -t atomsync-dev")
(run 'dev))}}} (run 'dev))}}}

View File

@@ -1,4 +1,4 @@
{:main pocketbook.todomvc {:main atomsync.todomvc
:output-to "example/todomvc/js/main.js" :output-to "example/todomvc/js/main.js"
:output-dir "example/todomvc/js/out" :output-dir "example/todomvc/js/out"
:asset-path "js/out" :asset-path "js/out"

View File

@@ -13,7 +13,7 @@
:extra-deps {io.github.cognitect-labs/test-runner :extra-deps {io.github.cognitect-labs/test-runner
{:git/tag "v0.5.1" :git/sha "dfb30dd"}}} {:git/tag "v0.5.1" :git/sha "dfb30dd"}}}
:test {:main-opts ["-m" "cognitect.test-runner"]} :test {:main-opts ["-m" "cognitect.test-runner"]}
:server {:main-opts ["-m" "pocketbook.server"]} :server {:main-opts ["-m" "atomsync.server"]}
;; ClojureScript client build ;; ClojureScript client build
:cljs {:extra-paths ["example/todomvc"] :cljs {:extra-paths ["example/todomvc"]
@@ -24,4 +24,4 @@
:cljs-dev {:extra-paths ["example/todomvc"] :cljs-dev {:extra-paths ["example/todomvc"]
:extra-deps {org.clojure/clojurescript {:mvn/version "1.11.132"} :extra-deps {org.clojure/clojurescript {:mvn/version "1.11.132"}
com.cognitect/transit-cljs {:mvn/version "0.8.280"}} com.cognitect/transit-cljs {:mvn/version "0.8.280"}}
:main-opts ["-m" "cljs.main" "-co" "build.edn" "-w" "src:example/todomvc/pocketbook" "-c"]}}} :main-opts ["-m" "cljs.main" "-co" "build.edn" "-w" "src:example/todomvc/atomsync" "-c"]}}}

View File

@@ -1,4 +1,4 @@
(ns pocketbook.hiccup (ns atomsync.hiccup
"Minimal hiccup → HTML string renderer." "Minimal hiccup → HTML string renderer."
(:require [clojure.string :as str])) (:require [clojure.string :as str]))

View File

@@ -1,8 +1,8 @@
(ns pocketbook.todomvc (ns atomsync.todomvc
"TodoMVC built on Pocketbook — offline-first, synced, Clojure-native." "TodoMVC built on Atomsync — offline-first, synced, Clojure-native."
(:require [pocketbook.core :as pb] (:require [atomsync.core :as pb]
[pocketbook.store.idb :as idb] [atomsync.store.idb :as idb]
[pocketbook.hiccup :refer [html]] [atomsync.hiccup :refer [html]]
[promesa.core :as p] [promesa.core :as p]
[clojure.string :as str])) [clojure.string :as str]))
@@ -232,7 +232,7 @@
;; --------------------------------------------------------------------------- ;; ---------------------------------------------------------------------------
(defn ^:export init [] (defn ^:export init []
(p/let [store (idb/open "pocketbook-todomvc")] (p/let [store (idb/open "atomsync-todomvc")]
(let [todos (pb/synced-atom store "todo" (let [todos (pb/synced-atom store "todo"
{:server "http://localhost:8090/sync" {:server "http://localhost:8090/sync"
:interval 15000})] :interval 15000})]
@@ -248,6 +248,6 @@
(.addEventListener js/window "offline" (fn [_] (render!))) (.addEventListener js/window "offline" (fn [_] (render!)))
;; Wait for IDB — watch triggers render automatically ;; Wait for IDB — watch triggers render automatically
(p/let [_ (pb/ready? todos)] (p/let [_ (pb/ready? todos)]
(js/console.log "🔶 Pocketbook TodoMVC loaded —" (count @todos) "todos"))))) (js/console.log "🔶 Atomsync TodoMVC loaded —" (count @todos) "todos")))))
(init) (init)

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pocketbook · TodoMVC</title> <title>Atomsync · TodoMVC</title>
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=DM+Mono:wght@300;400;500&family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;1,6..72,400&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=DM+Mono:wght@300;400;500&family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;1,6..72,400&display=swap" rel="stylesheet">
@@ -399,14 +399,14 @@
<body> <body>
<div class="wrapper"> <div class="wrapper">
<div class="brand"> <div class="brand">
<span class="brand-label">Pocketbook · TodoMVC</span> <span class="brand-label">Atomsync · TodoMVC</span>
</div> </div>
<div id="app"> <div id="app">
<div class="loading">Loading from local store</div> <div class="loading">Loading from local store</div>
</div> </div>
<div class="info"> <div class="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p>Built with <a href="https://github.com/pocketbook">Pocketbook</a> — offline-first synced atoms for Clojure</p> <p>Built with <a href="https://github.com/atomsync">Atomsync</a> — offline-first synced atoms for Clojure</p>
<p>Data persists in IndexedDB · syncs via Transit to SQLite</p> <p>Data persists in IndexedDB · syncs via Transit to SQLite</p>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
(ns pocketbook.core (ns atomsync.core
"Pocketbook: a Clojure-native synced atom. "Atomsync: a Clojure-native synced atom.
Usage: Usage:
(def store @(idb/open \"my-app\")) ;; or (memory/create) (def store @(idb/open \"my-app\")) ;; or (memory/create)
@@ -9,8 +9,8 @@
(fn [_] (swap! todos assoc \"todo:1\" {:text \"Buy milk\"}))) (fn [_] (swap! todos assoc \"todo:1\" {:text \"Buy milk\"})))
@todos ;=> {\"todo:1\" {:text \"Buy milk\"}} @todos ;=> {\"todo:1\" {:text \"Buy milk\"}}
" "
(:require [pocketbook.store :as store] (:require [atomsync.store :as store]
[pocketbook.sync :as sync] [atomsync.sync :as sync]
[clojure.string :as str] [clojure.string :as str]
[promesa.core :as p]) [promesa.core :as p])
#?(:clj (:import [java.util.concurrent Executors ScheduledExecutorService TimeUnit]))) #?(:clj (:import [java.util.concurrent Executors ScheduledExecutorService TimeUnit])))

View File

@@ -1,4 +1,4 @@
(ns pocketbook.db (ns atomsync.db
"SQLite storage layer with Nippy serialization. "SQLite storage layer with Nippy serialization.
Stores documents as binary blobs preserving all Clojure types." Stores documents as binary blobs preserving all Clojure types."
(:require [next.jdbc :as jdbc] (:require [next.jdbc :as jdbc]

View File

@@ -1,5 +1,5 @@
(ns pocketbook.server (ns atomsync.server
"Pocketbook sync server. Single-file HTTP server backed by SQLite. "Atomsync sync server. Single-file HTTP server backed by SQLite.
Endpoints: Endpoints:
GET /sync?since=T&group=G pull changes since timestamp GET /sync?since=T&group=G pull changes since timestamp
@@ -7,10 +7,10 @@
Start: Start:
clj -M:server clj -M:server
bb -m pocketbook.server" bb -m atomsync.server"
(:require [org.httpkit.server :as http] (:require [org.httpkit.server :as http]
[pocketbook.db :as db] [atomsync.db :as db]
[pocketbook.transit :as t] [atomsync.transit :as t]
[clojure.string :as str] [clojure.string :as str]
[clojure.java.io :as io]) [clojure.java.io :as io])
(:gen-class)) (:gen-class))
@@ -21,7 +21,7 @@
(def default-config (def default-config
{:port 8090 {:port 8090
:db-path "pocketbook.db" :db-path "atomsync.db"
:static-dir nil ;; nil = no static serving, or path like "example/todomvc" :static-dir nil ;; nil = no static serving, or path like "example/todomvc"
:cors true}) :cors true})
@@ -205,7 +205,7 @@
;; --------------------------------------------------------------------------- ;; ---------------------------------------------------------------------------
(defn start! (defn start!
"Start the Pocketbook server. Returns a stop function." "Start the Atomsync server. Returns a stop function."
([] ([]
(start! {})) (start! {}))
([config] ([config]
@@ -213,7 +213,7 @@
ds (db/open (:db-path config)) ds (db/open (:db-path config))
handler (make-handler ds config) handler (make-handler ds config)
server (http/run-server handler {:port (:port config)})] server (http/run-server handler {:port (:port config)})]
(println (str "🔶 Pocketbook server running on http://localhost:" (:port config))) (println (str "🔶 Atomsync server running on http://localhost:" (:port config)))
(println (str " Database: " (:db-path config))) (println (str " Database: " (:db-path config)))
(when (:static-dir config) (when (:static-dir config)
(println (str " Static: " (:static-dir config))) (println (str " Static: " (:static-dir config)))

View File

@@ -1,5 +1,5 @@
(ns pocketbook.store (ns atomsync.store
"Storage protocol for Pocketbook. "Storage protocol for Atomsync.
All methods return promesa promises.") All methods return promesa promises.")
(defprotocol PStore (defprotocol PStore

View File

@@ -1,7 +1,7 @@
(ns pocketbook.store.idb (ns atomsync.store.idb
"IndexedDB store implementing the PStore protocol." "IndexedDB store implementing the PStore protocol."
(:require [pocketbook.store :as store] (:require [atomsync.store :as store]
[pocketbook.transit :as transit] [atomsync.transit :as transit]
[promesa.core :as p])) [promesa.core :as p]))
;; --------------------------------------------------------------------------- ;; ---------------------------------------------------------------------------

View File

@@ -1,6 +1,6 @@
(ns pocketbook.store.memory (ns atomsync.store.memory
"In-memory store backed by atoms. Useful for testing and JVM clients." "In-memory store backed by atoms. Useful for testing and JVM clients."
(:require [pocketbook.store :as store] (:require [atomsync.store :as store]
[promesa.core :as p] [promesa.core :as p]
[clojure.string :as str])) [clojure.string :as str]))

View File

@@ -1,6 +1,6 @@
(ns pocketbook.sync (ns atomsync.sync
"HTTP sync client — pull and push documents to/from the Pocketbook server." "HTTP sync client — pull and push documents to/from the Atomsync server."
(:require [pocketbook.transit :as transit] (:require [atomsync.transit :as transit]
[clojure.string :as str] [clojure.string :as str]
[promesa.core :as p]) [promesa.core :as p])
#?(:clj (:import [java.net URI] #?(:clj (:import [java.net URI]

View File

@@ -1,4 +1,4 @@
(ns pocketbook.transit (ns atomsync.transit
"Transit encoding/decoding helpers for the HTTP wire format." "Transit encoding/decoding helpers for the HTTP wire format."
(:require [cognitect.transit :as t]) (:require [cognitect.transit :as t])
#?(:clj (:import [java.io ByteArrayInputStream ByteArrayOutputStream]))) #?(:clj (:import [java.io ByteArrayInputStream ByteArrayOutputStream])))

View File

@@ -1,10 +1,10 @@
(ns pocketbook.core-test (ns atomsync.core-test
(:require [clojure.test :refer [deftest is testing use-fixtures]] (:require [clojure.test :refer [deftest is testing use-fixtures]]
[promesa.core :as p] [promesa.core :as p]
[pocketbook.core :as pb] [atomsync.core :as pb]
[pocketbook.store :as store] [atomsync.store :as store]
[pocketbook.store.memory :as memory] [atomsync.store.memory :as memory]
[pocketbook.server :as server]) [atomsync.server :as server])
(:import [java.io File])) (:import [java.io File]))
;; --------------------------------------------------------------------------- ;; ---------------------------------------------------------------------------
@@ -21,7 +21,7 @@
(use-fixtures :each (use-fixtures :each
(fn [f] (fn [f]
(let [port (free-port) (let [port (free-port)
db-path (str (File/createTempFile "pocketbook-core-test" ".db")) db-path (str (File/createTempFile "atomsync-core-test" ".db"))
srv (server/start! {:port port :db-path db-path})] srv (server/start! {:port port :db-path db-path})]
(Thread/sleep 200) (Thread/sleep 200)
(try (try

View File

@@ -1,12 +1,12 @@
(ns pocketbook.db-test (ns atomsync.db-test
(:require [clojure.test :refer [deftest is testing use-fixtures]] (:require [clojure.test :refer [deftest is testing use-fixtures]]
[pocketbook.db :as db]) [atomsync.db :as db])
(:import [java.io File])) (:import [java.io File]))
(def ^:dynamic *ds* nil) (def ^:dynamic *ds* nil)
(defn- temp-db-path [] (defn- temp-db-path []
(str (File/createTempFile "pocketbook-test" ".db"))) (str (File/createTempFile "atomsync-test" ".db")))
(use-fixtures :each (use-fixtures :each
(fn [f] (fn [f]

View File

@@ -1,7 +1,7 @@
(ns pocketbook.server-test (ns atomsync.server-test
(:require [clojure.test :refer [deftest is testing use-fixtures]] (:require [clojure.test :refer [deftest is testing use-fixtures]]
[pocketbook.server :as server] [atomsync.server :as server]
[pocketbook.transit :as t]) [atomsync.transit :as t])
(:import [java.io File] (:import [java.io File]
[java.net URI] [java.net URI]
[java.net.http HttpClient HttpRequest HttpResponse$BodyHandlers HttpRequest$BodyPublishers])) [java.net.http HttpClient HttpRequest HttpResponse$BodyHandlers HttpRequest$BodyPublishers]))
@@ -16,7 +16,7 @@
(use-fixtures :each (use-fixtures :each
(fn [f] (fn [f]
(let [port (free-port) (let [port (free-port)
db-path (str (File/createTempFile "pocketbook-server-test" ".db")) db-path (str (File/createTempFile "atomsync-server-test" ".db"))
srv (server/start! {:port port :db-path db-path})] srv (server/start! {:port port :db-path db-path})]
(Thread/sleep 200) ;; let server start (Thread/sleep 200) ;; let server start
(try (try

View File

@@ -1,6 +1,6 @@
(ns pocketbook.transit-test (ns atomsync.transit-test
(:require [clojure.test :refer [deftest is testing]] (:require [clojure.test :refer [deftest is testing]]
[pocketbook.transit :as t])) [atomsync.transit :as t]))
(deftest roundtrip-basic-types (deftest roundtrip-basic-types
(doseq [v [42 (doseq [v [42