Просмотр исходного кода

Switched API-facing map keys to hyphenated keywords

Tienson Qin 4 недель назад
Родитель
Сommit
cc95768288

+ 1 - 0
AGENTS.md

@@ -20,6 +20,7 @@
 - ClojureScript keywords are defined via `logseq.common.defkeywords/defkeyword`; use existing keywords and add new ones in the shared definitions.
 - Follow existing namespace and file layout; keep related workers and RTC code in their dedicated directories.
 - Prefer concise, imperative commit subjects aligned with existing history (examples: `fix: download`, `enhance(rtc): ...`).
+- Clojure map keyword name should prefer `-` instead of `_`, e.g. `:user-id` instead of `:user_id`.
 
 ## Testing Guidelines
 - Unit tests live in `src/test/` and should be runnable via `bb dev:lint-and-test`.

+ 2 - 1
deps/common/src/logseq/common/authorization.cljs

@@ -7,6 +7,7 @@
 
 (def ^:private jwks-ttl-ms (* 6 60 60 1000))
 (def ^:private token-ttl-ms (* 60 60 1000))
+(def ^:private token-capacity 200)
 
 (defonce ^:private *jwks-cache (atom {:url nil :keys nil :fetched-at 0}))
 (defonce ^:private *token-cache (atom {}))
@@ -27,7 +28,7 @@
   (let [exp (aget payload "exp")]
     (when (number? exp)
       (swap! *token-cache assoc token {:payload payload :exp exp :cached-at now-ms}))
-    (when (> (count @*token-cache) 2000)
+    (when (> (count @*token-cache) token-capacity)
       (swap! *token-cache
              (fn [cache]
                (into {}

+ 9 - 9
deps/db-sync/src/logseq/db_sync/index.cljs

@@ -44,11 +44,11 @@
                                    user-id)
             rows (common/get-sql-rows result)]
       (mapv (fn [row]
-              {:graph_id (aget row "graph_id")
-               :graph_name (aget row "graph_name")
-               :schema_version (aget row "schema_version")
-               :created_at (aget row "created_at")
-               :updated_at (aget row "updated_at")})
+              {:graph-id (aget row "graph_id")
+               :graph-name (aget row "graph_name")
+               :schema-version (aget row "schema_version")
+               :created-at (aget row "created_at")
+               :updated-at (aget row "updated_at")})
             rows))
     []))
 
@@ -131,11 +131,11 @@
                                  graph-id)
           rows (common/get-sql-rows result)]
     (mapv (fn [row]
-            {:user_id (aget row "user_id")
-             :graph_id (aget row "graph_id")
+            {:user-id (aget row "user_id")
+             :graph-id (aget row "graph_id")
              :role (aget row "role")
-             :invited_by (aget row "invited_by")
-             :created_at (aget row "created_at")
+             :invited-by (aget row "invited_by")
+             :created-at (aget row "created_at")
              :email (aget row "email")
              :username (aget row "username")})
           rows)))

+ 19 - 19
deps/db-sync/src/logseq/db_sync/malli_schema.cljs

@@ -20,14 +20,14 @@
    ["tx/batch"
     [:map
      [:type [:= "tx/batch"]]
-     [:t_before :int]
+     [:t-before :int]
      [:txs :string]]]
    ["ping"
     [:map
      [:type [:= "ping"]]]]])
 
 (def tx-reject-reason-schema
-  [:enum "stale" "cycle" "empty tx data" "invalid tx" "invalid t_before"])
+  [:enum "stale" "cycle" "empty tx data" "invalid tx" "invalid t-before"])
 
 (def tx-reject-schema
   [:map
@@ -38,7 +38,7 @@
 
 (def user-presence-schema
   [:map
-   [:user_id :string]
+   [:user-id :string]
    [:email {:optional true} [:maybe :string]]
    [:username {:optional true} [:maybe :string]]
    [:name {:optional true} [:maybe :string]]])
@@ -91,22 +91,22 @@
 
 (def graph-info-schema
   [:map
-   [:graph_id :string]
-   [:graph_name :string]
-   [:schema_version {:optional true} [:maybe :string]]
-   [:created_at :int]
-   [:updated_at :int]])
+   [:graph-id :string]
+   [:graph-name :string]
+   [:schema-version {:optional true} [:maybe :string]]
+   [:created-at :int]
+   [:updated-at :int]])
 
 (def graph-member-role-schema
   [:enum "manager" "member"])
 
 (def graph-member-info-schema
   [:map
-   [:user_id :string]
-   [:graph_id :string]
+   [:user-id :string]
+   [:graph-id :string]
    [:role graph-member-role-schema]
-   [:invited_by {:optional true} [:maybe :string]]
-   [:created_at :int]
+   [:invited-by {:optional true} [:maybe :string]]
+   [:created-at :int]
    [:email {:optional true} [:maybe :string]]
    [:username {:optional true} [:maybe :string]]])
 
@@ -120,24 +120,24 @@
 
 (def graph-create-request-schema
   [:map
-   [:graph_name :string]
-   [:schema_version {:optional true} [:maybe :string]]])
+   [:graph-name :string]
+   [:schema-version {:optional true} [:maybe :string]]])
 
 (def graph-create-response-schema
   [:map
-   [:graph_id :string]])
+   [:graph-id :string]])
 
 (def graph-access-response-schema http-ok-response-schema)
 
 (def graph-delete-response-schema
   [:map
-   [:graph_id :string]
+   [:graph-id :string]
    [:deleted :boolean]])
 
 (def graph-member-create-request-schema
   [:or
    [:map
-    [:user_id :string]
+    [:user-id :string]
     [:role {:optional true} graph-member-role-schema]]
    [:map
     [:email :string]
@@ -149,7 +149,7 @@
 
 (def tx-batch-request-schema
   [:map
-   [:t_before :int]
+   [:t-before :int]
    [:txs :string]])
 
 (def snapshot-row-schema
@@ -163,7 +163,7 @@
 (def snapshot-rows-response-schema
   [:map
    [:rows [:sequential snapshot-row-schema]]
-   [:last_addr :int]
+   [:last-addr :int]
    [:done :boolean]])
 
 (def snapshot-import-request-schema

+ 11 - 11
deps/db-sync/src/logseq/db_sync/worker.cljs

@@ -141,7 +141,7 @@
                        (aget claims "username"))
           name (aget claims "name")]
       (when (string? user-id)
-        (cond-> {:user_id user-id}
+        (cond-> {:user-id user-id}
           (string? email) (assoc :email email)
           (string? username) (assoc :username username)
           (string? name) (assoc :name name))))))
@@ -393,7 +393,7 @@
     (cond
       (or (not (number? t-before)) (neg? t-before))
       {:type "tx/reject"
-       :reason "invalid t_before"}
+       :reason "invalid t-before"}
 
       (not= t-before current-t)
       {:type "tx/reject"
@@ -433,7 +433,7 @@
 
         "tx/batch"
         (let [txs (:txs message)
-              t-before (parse-int (:t_before message))]
+              t-before (parse-int (:t-before message))]
           (if (string? txs)
             (send! ws (handle-tx-batch! self ws txs t-before))
             (send! ws {:type "tx/reject" :reason "invalid tx"})))
@@ -508,7 +508,7 @@
                               after)
                   done? (< (count rows) limit)]
               (json-response :sync/snapshot-rows {:rows rows
-                                                  :last_addr last-addr
+                                                  :last-addr last-addr
                                                   :done done?}))
 
             (and (= method "DELETE") (= path "/admin/reset"))
@@ -530,8 +530,8 @@
                              body (coerce-http-request :sync/tx-batch body)]
                          (if (nil? body)
                            (bad-request "invalid tx")
-                           (let [{:keys [txs t_before]} body
-                                 t-before (parse-int t_before)]
+                           (let [{:keys [txs t-before]} body
+                                 t-before (parse-int t-before)]
                              (if (string? txs)
                                (json-response :sync/tx-batch (handle-tx-batch! self nil txs t-before))
                                (bad-request "invalid tx"))))))))
@@ -647,10 +647,10 @@
                            (bad-request "invalid body")
 
                            :else
-                           (p/let [{:keys [graph_name schema_version]} body
-                                   _ (index/<index-upsert! db graph-id graph_name user-id schema_version)
+                           (p/let [{:keys [graph-name schema-version]} body
+                                   _ (index/<index-upsert! db graph-id graph-name user-id schema-version)
                                    _ (index/<graph-member-upsert! db graph-id user-id "manager" user-id)]
-                             (json-response :graphs/create {:graph_id graph-id})))))))
+                             (json-response :graphs/create {:graph-id graph-id})))))))
 
             (and (= method "GET")
                  (= 3 (count parts))
@@ -702,7 +702,7 @@
                            (bad-request "missing body")
                            (let [body (js->clj result :keywordize-keys true)
                                  body (coerce-http-request :graph-members/create body)
-                                 member-id (:user_id body)
+                                 member-id (:user-id body)
                                  email (:email body)
                                  role (or (:role body) "member")]
                              (cond
@@ -801,7 +801,7 @@
                             stub (.get namespace do-id)
                             reset-url (str (.-origin url) "/admin/reset")]
                         (.fetch stub (js/Request. reset-url #js {:method "DELETE"})))
-                      (json-response :graphs/delete {:graph_id graph-id :deleted true}))))))
+                      (json-response :graphs/delete {:graph-id graph-id :deleted true}))))))
             :else
             (not-found))))
       (catch :default error

+ 29 - 23
deps/db-sync/test/logseq/db_sync/index_test.cljs

@@ -4,10 +4,16 @@
             [logseq.db-sync.index :as index]
             [promesa.core :as p]))
 
+(defn- js-key [k]
+  (cond
+    (keyword? k) (string/replace (name k) "-" "_")
+    (string? k) k
+    :else (str k)))
+
 (defn- js-row [m]
   (let [o (js-obj)]
     (doseq [[k v] m]
-      (aset o (name k) v))
+      (aset o (js-key k) v))
     o))
 
 (defn- js-rows [rows]
@@ -23,7 +29,7 @@
     (let [[user-id email email-verified username] args]
       (swap! state update :users assoc user-id {:id user-id
                                                 :email email
-                                                :email_verified email-verified
+                                                :email-verified email-verified
                                                 :username username}))
 
     (string/includes? sql "insert into graph_members")
@@ -32,21 +38,21 @@
              (fn [members]
                (let [k [user-id graph-id]
                      existing (get members k)
-                     created-at (or (:created_at existing) created-at)]
-                 (assoc members k {:user_id user-id
-                                   :graph_id graph-id
+                     created-at (or (:created-at existing) created-at)]
+                 (assoc members k {:user-id user-id
+                                   :graph-id graph-id
                                    :role role
-                                   :invited_by invited-by
-                                   :created_at created-at})))))
+                                   :invited-by invited-by
+                                   :created-at created-at})))))
 
     (string/includes? sql "insert into graphs")
     (let [[graph-id graph-name user-id schema-version created-at updated-at] args]
-      (swap! state update :graphs assoc graph-id {:graph_id graph-id
-                                                  :graph_name graph-name
-                                                  :user_id user-id
-                                                  :schema_version schema-version
-                                                  :created_at created-at
-                                                  :updated_at updated-at}))
+      (swap! state update :graphs assoc graph-id {:graph-id graph-id
+                                                  :graph-name graph-name
+                                                  :user-id user-id
+                                                  :schema-version schema-version
+                                                  :created-at created-at
+                                                  :updated-at updated-at}))
 
     (string/includes? sql "update graph_members set role")
     (let [[role graph-id user-id] args]
@@ -65,7 +71,7 @@
 
 (defn- union-access-rows [state sql args]
   (let [[graph-id user-id] args
-        graph-owner-id (get-in @state [:graphs graph-id :user_id])
+        graph-owner-id (get-in @state [:graphs graph-id :user-id])
         member (get-in @state [:graph-members [user-id graph-id]])
         manager-required? (string/includes? sql "role = 'manager'")
         has-access? (or (= graph-owner-id user-id)
@@ -73,7 +79,7 @@
                              (or (not manager-required?)
                                  (= "manager" (:role member)))))]
     (if has-access?
-      (js-rows [{:graph_id graph-id}])
+      (js-rows [{:graph-id graph-id}])
       (js-rows []))))
 
 (defn- all-sql [state sql args]
@@ -83,8 +89,8 @@
     (let [graph-id (first args)
           members (->> (:graph-members @state)
                        vals
-                       (filter (fn [row] (= graph-id (:graph_id row))))
-                       (sort-by :created_at))]
+                       (filter (fn [row] (= graph-id (:graph-id row))))
+                       (sort-by :created-at))]
       (js-rows members))
 
     (string/includes? sql "union select graph_id from graph_members")
@@ -94,15 +100,15 @@
     (let [[user-id] args
           owned (->> (:graphs @state)
                      vals
-                     (filter (fn [row] (= user-id (:user_id row)))))
+                     (filter (fn [row] (= user-id (:user-id row)))))
           member-ids (->> (:graph-members @state)
                           vals
-                          (filter (fn [row] (= user-id (:user_id row))))
-                          (map :graph_id)
+                          (filter (fn [row] (= user-id (:user-id row))))
+                          (map :graph-id)
                           set)
           member-graphs (->> (:graphs @state)
                              vals
-                             (filter (fn [row] (contains? member-ids (:graph_id row)))))]
+                             (filter (fn [row] (contains? member-ids (:graph-id row)))))]
       (js-rows (concat owned member-graphs)))
 
     :else
@@ -158,7 +164,7 @@
                (p/then (fn [_]
                          (let [user (get-in @state [:users "user-1"])]
                            (is (= "[email protected]" (:email user)))
-                           (is (= 1 (:email_verified user)))
+                           (is (= 1 (:email-verified user)))
                            (is (= "foo" (:username user))))
                          (done)))
                (p/catch (fn [e]
@@ -176,7 +182,7 @@
                (p/then (fn [_]
                          (let [member (get-in @state [:graph-members ["user-2" "graph-1"]])]
                            (is (= "member" (:role member)))
-                           (is (= "user-1" (:invited_by member))))
+                           (is (= "user-1" (:invited-by member))))
                          (done)))
                (p/catch (fn [e]
                           (is false (str e))

+ 8 - 2
deps/db-sync/test/logseq/db_sync/test_sql.cljs

@@ -1,10 +1,16 @@
 (ns logseq.db-sync.test-sql
   (:require [clojure.string :as string]))
 
+(defn- js-key [k]
+  (cond
+    (keyword? k) (string/replace (name k) "-" "_")
+    (string? k) k
+    :else (str k)))
+
 (defn- js-row [m]
   (let [o (js-obj)]
     (doseq [[k v] m]
-      (aset o (name k) v))
+      (aset o (js-key k) v))
     o))
 
 (defn- js-rows [rows]
@@ -17,7 +23,7 @@
                  (cond
                    (string/includes? sql "insert into tx_log")
                    (let [[t tx created-at] args]
-                     (swap! state update :tx-log assoc t {:t t :tx tx :created_at created-at})
+                     (swap! state update :tx-log assoc t {:t t :tx tx :created-at created-at})
                      nil)
 
                    (string/includes? sql "select t, tx from tx_log")

+ 1 - 1
deps/db-sync/worker/scripts/dev_test.sh

@@ -20,7 +20,7 @@ echo
 
 curl -sS -X POST "${SYNC_BASE}/tx" \
   -H "content-type: application/json" \
-  --data-binary '{"t_before":0,"tx":"[]"}'
+  --data-binary '{"t-before":0,"tx":"[]"}'
 
 echo
 

+ 1 - 1
docs/agent-guide/db-sync/db-sync-guide.md

@@ -34,7 +34,7 @@ This guide helps AI agents implement and review db-sync features consistently ac
 - Server-side validation of client input should not throw. Respond with `tx/reject` or `400` errors for:
   - tx payload type mismatch (e.g., `:txs` not a sequence of strings).
   - Invalid graph identity (missing/empty graph id or uuid in sync path).
-  - Invalid or negative `t`/`t_before` values.
+  - Invalid or negative `t`/`t-before` values.
 - Do not silently recover or drop messages for bug cases; surface them via exceptions.
 
 ## HTTP API (Bootstrap + Assets)

+ 1 - 1
docs/agent-guide/db-sync/fix-blocks-cycle.md

@@ -8,7 +8,7 @@ This document describes the handling of cycles formed between multiple blocks in
 ## What the server returns
 - The reject payload includes:
   - `attr`: the attribute that introduced the cycle (for blocks this is `:block/parent`).
-  - `server_values`: a map of the affected entities to the server’s current value for `attr` (from `logseq.db-sync.cycle/server-values-for`).
+  - `server-values`: a map of the affected entities to the server’s current value for `attr` (from `logseq.db-sync.cycle/server-values-for`).
 - This allows the client to realign its local state to the server’s authoritative values.
 
 ## Client-side reconciliation

+ 11 - 11
docs/agent-guide/db-sync/protocol.md

@@ -11,15 +11,15 @@
   - Initial handshake from client.
 - `{"type":"pull","since":<t>}`
   - Request txs after `since` (defaults to 0).
-- `{"type":"tx/batch","t_before":<t>,"txs":["<tx-transit>", ...]}`
-  - Upload a batch of txs based on `t_before` (required).
+- `{"type":"tx/batch","t-before":<t>,"txs":["<tx-transit>", ...]}`
+  - Upload a batch of txs based on `t-before` (required).
 - `{"type":"ping"}`
   - Optional keepalive; server replies `pong`.
 
 ## Server -> Client
 - `{"type":"hello","t":<t>}`
   - Server hello with current t.
-- `{"type":"online-users","online-users":[{"user_id":"...","email":"...","username":"...","name":"..."}...]}`
+- `{"type":"online-users","online-users":[{"user-id":"...","email":"...","username":"...","name":"..."}...]}`
   - Presence update with currently online users (fields may be omitted).
 - `{"type":"pull/ok","t":<t>,"txs":[{"t":<t>,"tx":"<tx-transit>"}...]}`
   - Pull response with txs.
@@ -29,9 +29,9 @@
   - Broadcast that server state advanced; client should pull.
 - `{"type":"tx/reject","reason":"stale","t":<t>}`
   - Client tx is based on stale t.
-- `{"type":"tx/reject","reason":"cycle","data":"<transit {:attr <kw> :server_values ...}>"}`
+- `{"type":"tx/reject","reason":"cycle","data":"<transit {:attr <kw> :server-values ...}>"}`
   - Cycle detected with server values.
-- `{"type":"tx/reject","reason":"empty tx data"|"invalid tx"|"invalid t_before"}`
+- `{"type":"tx/reject","reason":"empty tx data"|"invalid tx"|"invalid t-before"}`
   - Invalid batch.
 - `{"type":"pong"}`
   - Keepalive response.
@@ -49,15 +49,15 @@
 
 ### Graphs (index DO)
 - `GET /graphs`
-  - List graphs the user owns. Response: `{"graphs":[{graph_id, graph_name, schema_version?, created_at, updated_at}...]}`.
+  - List graphs the user owns. Response: `{"graphs":[{graph-id, graph-name, schema-version?, created-at, updated-at}...]}`.
 - `POST /graphs`
-  - Create graph. Body: `{"graph_name":"...","schema_version":"<major>"}` (schema_version optional). Response: `{"graph_id":"..."}`.
+  - Create graph. Body: `{"graph-name":"...","schema-version":"<major>"}` (schema-version optional). Response: `{"graph-id":"..."}`.
 - `GET /graphs/:graph-id/access`
   - Access check. Response: `{"ok":true}`, `401` (unauthorized), `403` (forbidden), or `404` (not found).
 - `GET /graphs/:graph-id/members`
-  - Graph members list. Response: `{"members":[{user_id, graph_id, role, invited_by, created_at, email?, username?}...]}`.
+  - Graph members list. Response: `{"members":[{user-id, graph-id, role, invited-by, created-at, email?, username?}...]}`.
 - `DELETE /graphs/:graph-id`
-  - Delete graph and reset data. Response: `{"graph_id":"...","deleted":true}` or `400` (missing graph id).
+  - Delete graph and reset data. Response: `{"graph-id":"...","deleted":true}` or `400` (missing graph id).
 
 ### Sync (per-graph DO, via `/sync/:graph-id/...`)
 - `GET /sync/:graph-id/health`
@@ -66,11 +66,11 @@
   - Same as WS pull. Response: `{"type":"pull/ok","t":<t>,"txs":[{"t":<t>,"tx":"<tx-transit>"}...]}`.
   - Error response (400): `{"error":"invalid since"}`.
 - `POST /sync/:graph-id/tx/batch`
-  - Same as WS tx/batch. Body: `{"t_before":<t>,"txs":["<tx-transit>", ...]}`.
+  - Same as WS tx/batch. Body: `{"t-before":<t>,"txs":["<tx-transit>", ...]}`.
   - Response: `{"type":"tx/batch/ok","t":<t>}` or `{"type":"tx/reject","reason":...}`.
   - Error response (400): `{"error":"missing body"|"invalid tx"}`.
 - `GET /sync/:graph-id/snapshot/rows?after=<addr>&limit=<n>`
-  - Pull sqlite kvs rows. Response: `{"rows":[{"addr":<addr>,"content":"<transit>","addresses":<json|null>}...],"last_addr":<addr>,"done":true|false}`.
+  - Pull sqlite kvs rows. Response: `{"rows":[{"addr":<addr>,"content":"<transit>","addresses":<json|null>}...],"last-addr":<addr>,"done":true|false}`.
 - `POST /sync/:graph-id/snapshot/import`
   - Import sqlite kvs rows. Body: `{"reset":true|false,"rows":[[addr,content,addresses]...]}`.
   - Response: `{"ok":true,"count":<n>}`.

+ 12 - 12
src/main/frontend/handler/db_based/db_sync.cljs

@@ -113,10 +113,10 @@
                                  {:method "GET"}
                                  {:response-schema :graph-members/list})
                 members (:members resp)
-                users (mapv (fn [{:keys [user_id role email username]}]
-                              (let [name (or username email user_id)
+                users (mapv (fn [{:keys [user-id role email username]}]
+                              (let [name (or username email user-id)
                                     user-type (some-> role keyword)]
-                                (cond-> {:user/uuid user_id
+                                (cond-> {:user/uuid user-id
                                          :user/name name
                                          :graph<->user/user-type user-type}
                                   (string? email) (assoc :user/email email))))
@@ -131,8 +131,8 @@
     (if base
       (p/let [_ (js/Promise. user-handler/task--ensure-id&access-token)
               body (coerce-http-request :graphs/create
-                                        {:graph_name (string/replace repo config/db-version-prefix "")
-                                         :schema_version schema-version})
+                                        {:graph-name (string/replace repo config/db-version-prefix "")
+                                         :schema-version schema-version})
               result (if (nil? body)
                        (p/rejected (ex-info "db-sync invalid create-graph body"
                                             {:repo repo}))
@@ -141,7 +141,7 @@
                                     :headers {"content-type" "application/json"}
                                     :body (js/JSON.stringify (clj->js body))}
                                    {:response-schema :graphs/create}))
-              graph-id (:graph_id result)]
+              graph-id (:graph-id result)]
         (if graph-id
           (p/do!
            (ldb/transact! repo [(sqlite-util/kv :logseq.kv/db-type "db")
@@ -190,7 +190,7 @@
                                        {:response-schema :sync/snapshot-rows})
                       rows (:rows resp)
                       done? (true? (:done resp))
-                      last-addr (or (:last_addr resp) after)]
+                      last-addr (or (:last-addr resp) after)]
                 (p/do!
                  (state/<invoke-db-worker :thread-api/db-sync-import-kvs-rows
                                           graph rows first-batch?)
@@ -220,12 +220,12 @@
                   graphs (:graphs resp)
                   result (mapv (fn [graph]
                                  (merge
-                                  {:url (str config/db-version-prefix (:graph_name graph))
-                                   :GraphName (:graph_name graph)
-                                   :GraphSchemaVersion (:schema_version graph)
-                                   :GraphUUID (:graph_id graph)
+                                  {:url (str config/db-version-prefix (:graph-name graph))
+                                   :GraphName (:graph-name graph)
+                                   :GraphSchemaVersion (:schema-version graph)
+                                   :GraphUUID (:graph-id graph)
                                    :rtc-graph? true}
-                                  (dissoc graph :graph_id :graph_name :schema_version)))
+                                  (dissoc graph :graph-id :graph-name :schema-version)))
                                graphs)]
             (state/set-state! :rtc/graphs result)
             (repo-handler/refresh-repos!)

+ 5 - 5
src/main/frontend/worker/db_sync.cljs

@@ -51,10 +51,10 @@
 (defn- normalize-online-users
   [users]
   (->> users
-       (keep (fn [{:keys [user_id email username name]}]
-               (when (string? user_id)
-                 (let [display-name (or username name user_id)]
-                   (cond-> {:user/uuid user_id
+       (keep (fn [{:keys [user-id email username name]}]
+               (when (string? user-id)
+                 (let [display-name (or username name user-id)]
+                   (cond-> {:user/uuid user-id
                             :user/name display-name}
                      (string? email) (assoc :user/email email))))))
        (vec)))
@@ -403,7 +403,7 @@
                   (when (seq txs)
                     (reset! (:inflight client) tx-ids)
                     (send! ws {:type "tx/batch"
-                               :t_before local-tx
+                               :t-before local-tx
                                :txs (sqlite-util/write-transit-str tx-data)})))))))))))
 
 (defn- ensure-client-state! [repo]