;; Phase 2 — op log + versioning over persist. The log is the source of truth; ;; any version is a replay of the op stream up to a seq. (st-bootstrap-classes!) (content-bootstrap-blocks!) (content-bootstrap-doc!) (define B (persist/open)) (define h (mk-heading "h" 1 "Title")) (define p (mk-text "p" "Body")) (define img (mk-image "img" "/c.png" "cat")) ;; ── commit an op stream ── (content/commit! B "post" (op-insert h nil) 10) (content/commit! B "post" (op-insert p "h") 11) (content/commit! B "post" (op-insert img "h") 12) (content/commit! B "post" (op-update "p" "text" "Edited") 13) (content/commit! B "post" (op-delete "img") 14) (content-test "version-count" (content/version-count B "post") 5) (content-test "log length" (len (content/log B "post")) 5) ;; ── head: latest materialised document ── (content-test "head ids" (doc-ids (content/head B "post")) (list "h" "p")) (content-test "head p edited" (str (blk-send (doc-find (content/head B "post") "p") "text")) "Edited") ;; ── replay to any version ── (content-test "at seq1" (doc-ids (content/at B "post" 1)) (list "h")) (content-test "at seq2" (doc-ids (content/at B "post" 2)) (list "h" "p")) (content-test "at seq3" (doc-ids (content/at B "post" 3)) (list "h" "img" "p")) (content-test "at seq3 p original" (str (blk-send (doc-find (content/at B "post" 3) "p") "text")) "Body") (content-test "at seq4 p edited" (str (blk-send (doc-find (content/at B "post" 4) "p") "text")) "Edited") (content-test "at seq5 img gone" (doc-ids (content/at B "post" 5)) (list "h" "p")) (content-test "at seq0 empty" (doc-ids (content/at B "post" 0)) (list)) ;; ── ops accessor ── (content-test "ops kinds" (map (fn (o) (get o :op)) (content/ops B "post")) (list "insert" "insert" "insert" "update" "delete")) ;; ── history metadata ── (define hist (content/history B "post")) (content-test "history length" (len hist) 5) (content-test "history first seq" (get (first hist) :seq) 1) (content-test "history first type" (get (first hist) :type) "insert") (content-test "history first at" (get (first hist) :at) 10) (content-test "history fourth type" (get (nth hist 3) :type) "update") ;; ── diff between versions ── (define dvf (content/diff-versions B "post" 1 3)) (content-test "diff added" (get dvf :added) (list "img" "p")) (content-test "diff removed empty" (get dvf :removed) (list)) (content-test "diff changed empty" (get dvf :changed) (list)) (define dvf2 (content/diff-versions B "post" 3 5)) (content-test "diff2 removed" (get dvf2 :removed) (list "img")) (content-test "diff2 changed" (get dvf2 :changed) (list "p")) (content-test "diff2 added empty" (get dvf2 :added) (list)) ;; ── direct diff of two materialised docs ── (define da (content/at B "post" 2)) (define db (content/at B "post" 5)) (content-test "direct diff changed" (get (content/diff da db) :changed) (list "p")) (content-test "direct diff no-op" (get (content/diff da da) :changed) (list)) ;; ── commit-all batch ── (define B2 (persist/open)) (content/commit-all! B2 "doc2" (list (op-insert h nil) (op-insert p "h")) 1) (content-test "commit-all count" (content/version-count B2 "doc2") 2) (content-test "commit-all head" (doc-ids (content/head B2 "doc2")) (list "h" "p")) ;; ── stream isolation ── (content-test "separate stream empty" (content/version-count B "doc2") 0) (content-test "head of empty stream" (doc-ids (content/head B "never")) (list))