Skip to content

Refactor Doc class to delegate mutations through DocStore#68

Merged
hackerwins merged 7 commits into
mainfrom
refactor/docs-docstore-abstraction
Mar 22, 2026
Merged

Refactor Doc class to delegate mutations through DocStore#68
hackerwins merged 7 commits into
mainfrom
refactor/docs-docstore-abstraction

Conversation

@hackerwins

@hackerwins hackerwins commented Mar 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fix MemDocStore to use snapshot-only undo contract: only explicit snapshot() calls create undo entries, individual mutations no longer auto-push to undo stack
  • Add deleteBlockByIndex(index) to DocStore interface and MemDocStore
  • Refactor Doc class to take a DocStore in its constructor, delegate all mutations through store methods, and maintain a cached Document refreshed via refresh()
  • Replace direct blocks.splice() in TextEditor.deleteSelection() with doc.deleteBlockByIndex()
  • Remove syncToStore() from editor — Doc now writes through to the store directly

Context

This is the foundation for adding real-time collaborative editing via Yorkie's Tree CRDT (see docs/design/docs-collaboration.md). By routing all mutations through the DocStore interface, a future YorkieDocStore can be plugged in without changing Doc or TextEditor.

Test plan

  • All 125 docs package tests pass
  • pnpm verify:fast passes (1383+ tests across all packages)
  • TypeScript compilation clean for docs package (only pre-existing warnings in test fixtures)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

    • Improved document management architecture with store-backed mutation model for better consistency and state control across the editor.
  • Tests

    • Added block deletion coverage with bounds validation and updated undo/redo test expectations to reflect new operation sequencing.

hackerwins and others added 7 commits March 22, 2026 21:12
Per docs-collaboration design, only explicit snapshot() calls create
undo entries. Mutation methods no longer auto-push to undo stack.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Needed by Doc.deleteSelection() which removes middle blocks by
index during multi-block selection deletion.
Task 2 implementer reverted Task 1's snapshot-only undo changes.
Restore them: mutation methods do not call pushUndo() or clear
redoStack. Only snapshot() creates undo entries.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Doc now takes a DocStore in its constructor and delegates all
mutations (insert, delete, split, merge, style) through store
methods. Maintains a cached Document for reads, refreshed after
each mutation.
The design spec requires refresh() to be callable externally
when remote changes arrive via YorkieDocStore.
TextEditor now uses doc.deleteBlockByIndex() instead of directly
splicing doc.document.blocks, ensuring mutations go through DocStore.
Doc now receives the DocStore in its constructor so all mutations
go through the store automatically. syncToStore() is no longer
needed. Undo/redo uses doc.refresh() instead of directly
assigning doc.document.
@coderabbitai

coderabbitai Bot commented Mar 22, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

The Doc class transitions from in-place mutation to a store-backed architecture. Doc now holds a DocStore with a cached _document, exposes the document via getter, and provides a refresh() method to reload from the store. All mutation operations now delegate through the store and refresh the cache. A new deleteBlockByIndex() method is added to the store interface.

Changes

Cohort / File(s) Summary
Store-Backed Document Model
packages/docs/src/model/document.ts, packages/docs/src/store/store.ts, packages/docs/src/store/memory.ts
Refactored Doc to hold a DocStore instead of directly storing the document; added caching via _document and refresh(); all mutation paths now delegate through store operations and refresh the cache afterward; introduced deleteBlockByIndex(index) to the store interface and implementation; removed automatic undo snapshotting from store mutations.
View Layer Integration
packages/docs/src/view/editor.ts, packages/docs/src/view/text-editor.ts
Updated initialization to construct Doc from docStore directly; replaced direct document mutation with doc.refresh() for page margin and undo/redo operations; replaced array splice with deleteBlockByIndex() API call for block removal during multi-block selection deletion.
Store Test Coverage
packages/docs/test/store/memory.test.ts
Added tests for deleteBlockByIndex() with valid/invalid indices; updated undo/redo tests to require explicit snapshot() calls before mutations; added test asserting mutations without preceding snapshots are not undoable.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A doc once mutated in place,
Now stores with grace and stored embrace,
Through cache and refresh, mutations flow,
To persistence below we go,
The rabbit hops through cleaner code!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main architectural change: refactoring the Doc class to delegate mutations through DocStore instead of in-place mutation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/docs-docstore-abstraction

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

Verification: verify:self

Result: ✅ PASS in 95.8s

Lane Status Duration
sheets:build ✅ pass 13.0s
verify:fast ✅ pass 47.9s
frontend:build ✅ pass 13.5s
verify:frontend:chunks ✅ pass 0.3s
backend:build ✅ pass 4.3s
cli:build ✅ pass 1.8s
verify:entropy ✅ pass 14.9s

Verification: verify:integration

Result: ✅ PASS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant