Add history functionality to document management#279
Conversation
📝 WalkthroughWalkthroughDocumentation update to Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@docs/js-sdk.mdx`:
- Line 539: Update the revis ion intro sentence that currently reads "save
snapshots of your document at specific points in time" to remove the redundancy
and read "save snapshots of your document at specific points"; locate the
sentence mentioning "Yorkie provides revision management capabilities" and
replace the substring "specific points in time" with "specific points" in
docs/js-sdk.mdx.
- Around line 879-981: The intro and Supported Operations claims are too broad
and inconsistent with the local-only and partial-support notes; update the
phrasing around doc.history, doc.history.undo/redo, and the Supported Operations
list (mentioning Text.setStyle and Tree) to explicitly state history only tracks
local changes (not remote), that some features are experimental/under
development (e.g., Text.setStyle, Tree undo/redo), and avoid saying “all
document changes” or “all CRDT types”; keep the examples but add brief
qualifiers where they rely on local operations and mark Text.setStyle and Tree
as not fully supported yet so readers won’t expect global/complete undo
coverage.
- Around line 720-735: Update the revision workflow example so the final sync
explicitly targets the restored document: after calling
client.restoreRevision(doc, v1.id) replace the call to client.sync() with
client.sync(doc) to match the explicit pattern used elsewhere (see
createRevision, listRevisions, getRevision, restoreRevision and client.sync) and
make it clear the specific document is being synchronized.
| #### Managing Document Revisions | ||
|
|
||
| Yorkie provides revision management capabilities that allow you to save snapshots of your document at specific points in time, browse through document history, and restore previous versions. This is useful for implementing features like version control, undo/redo functionality, or audit trails in your collaborative applications. | ||
| Yorkie provides revision management capabilities that allow you to save snapshots of your document at specific points in time, browse through document history, and restore previous versions. This is useful for implementing features like version control, or audit trails in your collaborative applications. |
There was a problem hiding this comment.
Trim redundant phrasing in the revision intro.
“Specific points in time” is redundant and reads cleaner as “specific points.”
✏️ Suggested edit
-Yorkie provides revision management capabilities that allow you to save snapshots of your document at specific points in time, browse through document history, and restore previous versions. This is useful for implementing features like version control, or audit trails in your collaborative applications.
+Yorkie provides revision management capabilities that allow you to save snapshots of your document at specific points, browse through document history, and restore previous versions. This is useful for implementing features like version control, or audit trails in your collaborative applications.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Yorkie provides revision management capabilities that allow you to save snapshots of your document at specific points in time, browse through document history, and restore previous versions. This is useful for implementing features like version control, or audit trails in your collaborative applications. | |
| Yorkie provides revision management capabilities that allow you to save snapshots of your document at specific points, browse through document history, and restore previous versions. This is useful for implementing features like version control, or audit trails in your collaborative applications. |
🧰 Tools
🪛 LanguageTool
[style] ~539-~539: This phrase is redundant. Consider writing “points” or “times”.
Context: ... snapshots of your document at specific points in time, browse through document history, and r...
(MOMENT_IN_TIME)
🤖 Prompt for AI Agents
In `@docs/js-sdk.mdx` at line 539, Update the revis ion intro sentence that
currently reads "save snapshots of your document at specific points in time" to
remove the redundancy and read "save snapshots of your document at specific
points"; locate the sentence mentioning "Yorkie provides revision management
capabilities" and replace the substring "specific points in time" with "specific
points" in docs/js-sdk.mdx.
| **Example workflow:** | ||
|
|
||
| ```javascript | ||
| // Create a client and attach a document | ||
| const client = new yorkie.Client({ | ||
| rpcAddr: '{{API_ADDR}}', | ||
| apiKey: 'xxxxxxxxxxxxxxxxxxxx', | ||
| }); | ||
| await client.activate(); | ||
|
|
||
| const doc = new yorkie.Document('my-document'); | ||
| await client.attach(doc); | ||
|
|
||
| // Make some changes | ||
| doc.update((root) => { | ||
| root.title = 'My Document'; | ||
| root.content = 'Initial content'; | ||
| }); | ||
|
|
||
| // Create a revision to save this state | ||
| // Create a revision | ||
| const v1 = await client.createRevision(doc, 'v1.0', 'Initial version'); | ||
|
|
||
| // Make more changes | ||
| doc.update((root) => { | ||
| root.content = 'Updated content'; | ||
| }); | ||
|
|
||
| // Create another revision | ||
| const v2 = await client.createRevision(doc, 'v2.0', 'Updated content'); | ||
|
|
||
| // List all revisions | ||
| const revisions = await client.listRevisions(doc); | ||
| console.log(`Found ${revisions.length} revisions`); | ||
|
|
||
| // Get details of a specific revision | ||
| const revisionDetails = await client.getRevision(doc, v1.id); | ||
| console.log('V1.0 snapshot:', revisionDetails.snapshot); | ||
| // Get revision details with snapshot | ||
| const revision = await client.getRevision(doc, v1.id); | ||
|
|
||
| // Restore to v1.0 | ||
| // Restore to a previous revision | ||
| await client.restoreRevision(doc, v1.id); | ||
| await client.sync(); | ||
|
|
||
| console.log('Restored to v1.0'); | ||
| ``` |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's check if docs/js-sdk.mdx exists and examine the relevant lines
wc -l docs/js-sdk.mdxRepository: yorkie-team/yorkie-team.github.io
Length of output: 97
🏁 Script executed:
# Read around line 534 to see the first sync() usage
sed -n '530,540p' docs/js-sdk.mdxRepository: yorkie-team/yorkie-team.github.io
Length of output: 690
🏁 Script executed:
# Read around line 734 to see the second sync() usage
sed -n '730,740p' docs/js-sdk.mdxRepository: yorkie-team/yorkie-team.github.io
Length of output: 559
🏁 Script executed:
# Search for the Client class and sync method in the SDK source
find . -type f \( -name "*.ts" -o -name "*.js" \) | head -20
rg -n "class Client" --type=ts --type=js | head -10Repository: yorkie-team/yorkie-team.github.io
Length of output: 50389
🏁 Script executed:
# Look for sync method definitions in the codebase
rg -n "sync\s*\(" --type=ts --type=js -B 2 -A 5 | head -50Repository: yorkie-team/yorkie-team.github.io
Length of output: 50390
🏁 Script executed:
# Search for sync method definition in SDK or documentation
rg -i "sync.*function|sync.*method|function sync" --type=ts --type=js --type=mdx -A 5 | head -80Repository: yorkie-team/yorkie-team.github.io
Length of output: 104
🏁 Script executed:
# Look for JSDoc comments around sync function
rg -B 5 "sync\(" docs/js-sdk.mdx | head -40Repository: yorkie-team/yorkie-team.github.io
Length of output: 777
🏁 Script executed:
# Check if there's any SDK reference documentation
find . -name "*.md" -o -name "*.mdx" | xargs grep -l "sync.*signature\|client\.sync" 2>/dev/null | head -10Repository: yorkie-team/yorkie-team.github.io
Length of output: 136
🏁 Script executed:
# Search for all occurrences of sync() in the docs to understand pattern
rg "sync\(\)" docs/js-sdk.mdx -B 2 -A 2Repository: yorkie-team/yorkie-team.github.io
Length of output: 261
🏁 Script executed:
# Look for sync method in other SDK docs for comparison
rg "sync\(" docs/ -B 1 -A 1 | head -60Repository: yorkie-team/yorkie-team.github.io
Length of output: 2263
🏁 Script executed:
# Check if there's a code example directory or SDK reference
find . -type f \( -name "*.ts" -o -name "*.js" \) -path "*/sdk*" -o -path "*/examples*" | grep -E "(client|sync)" | head -20Repository: yorkie-team/yorkie-team.github.io
Length of output: 59
🏁 Script executed:
# Final attempt to find JS SDK documentation or source
find . -name "*.md" -o -name "*.mdx" | xargs grep -i "sync.*optional\|sync.*parameter\|sync.*overload" 2>/dev/nullRepository: yorkie-team/yorkie-team.github.io
Length of output: 852
Align client.sync() calls to consistently include the document parameter in the revision workflow example.
While client.sync() accepts an optional document parameter (per the SDK design, it can sync all attached documents when omitted), the revision workflow example at line 734 should be updated to match the explicit pattern used in the manual sync example at line 534. After calling client.restoreRevision(doc, v1.id), use await client.sync(doc); to clearly indicate that the specific document's state is being synchronized, improving consistency and clarity for users following the example.
Suggested change
// Restore to a previous revision
await client.restoreRevision(doc, v1.id);
-await client.sync();
+await client.sync(doc);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| **Example workflow:** | |
| ```javascript | |
| // Create a client and attach a document | |
| const client = new yorkie.Client({ | |
| rpcAddr: '{{API_ADDR}}', | |
| apiKey: 'xxxxxxxxxxxxxxxxxxxx', | |
| }); | |
| await client.activate(); | |
| const doc = new yorkie.Document('my-document'); | |
| await client.attach(doc); | |
| // Make some changes | |
| doc.update((root) => { | |
| root.title = 'My Document'; | |
| root.content = 'Initial content'; | |
| }); | |
| // Create a revision to save this state | |
| // Create a revision | |
| const v1 = await client.createRevision(doc, 'v1.0', 'Initial version'); | |
| // Make more changes | |
| doc.update((root) => { | |
| root.content = 'Updated content'; | |
| }); | |
| // Create another revision | |
| const v2 = await client.createRevision(doc, 'v2.0', 'Updated content'); | |
| // List all revisions | |
| const revisions = await client.listRevisions(doc); | |
| console.log(`Found ${revisions.length} revisions`); | |
| // Get details of a specific revision | |
| const revisionDetails = await client.getRevision(doc, v1.id); | |
| console.log('V1.0 snapshot:', revisionDetails.snapshot); | |
| // Get revision details with snapshot | |
| const revision = await client.getRevision(doc, v1.id); | |
| // Restore to v1.0 | |
| // Restore to a previous revision | |
| await client.restoreRevision(doc, v1.id); | |
| await client.sync(); | |
| console.log('Restored to v1.0'); | |
| ``` | |
| **Example workflow:** | |
🤖 Prompt for AI Agents
In `@docs/js-sdk.mdx` around lines 720 - 735, Update the revision workflow example
so the final sync explicitly targets the restored document: after calling
client.restoreRevision(doc, v1.id) replace the call to client.sync() with
client.sync(doc) to match the explicit pattern used elsewhere (see
createRevision, listRevisions, getRevision, restoreRevision and client.sync) and
make it clear the specific document is being synchronized.
| Yorkie provides built-in undo/redo functionality for all document changes. This allows users to revert or reapply changes made to the document, making it ideal for collaborative editors and applications requiring change history. | ||
|
|
||
| ##### Basic Usage | ||
|
|
||
| You can undo and redo changes using the `document.history` API: | ||
|
|
||
| ```javascript | ||
| doc.update((root) => { | ||
| root.text = new yorkie.Text(); | ||
| root.text.edit(0, 0, 'Hello'); | ||
| }); | ||
|
|
||
| // Undo the last change | ||
| doc.history.undo(); | ||
| console.log(doc.getRoot().text.toString()); // "" | ||
|
|
||
| // Redo the undone change | ||
| doc.history.redo(); | ||
| console.log(doc.getRoot().text.toString()); // "Hello" | ||
| ``` | ||
|
|
||
| ##### Checking Undo/Redo Availability | ||
|
|
||
| Before calling `undo()` or `redo()`, you can check if these operations are available: | ||
|
|
||
| ```javascript | ||
| doc.update((root) => { | ||
| root.counter = new yorkie.Counter(yorkie.IntType, 0); | ||
| root.counter.increase(5); | ||
| }); | ||
|
|
||
| console.log(doc.history.canUndo()); // true | ||
| console.log(doc.history.canRedo()); // false | ||
|
|
||
| doc.history.undo(); | ||
| console.log(doc.history.canUndo()); // false | ||
| console.log(doc.history.canRedo()); // true | ||
| ``` | ||
|
|
||
| ##### Redo Stack Behavior | ||
|
|
||
| When you make a new change after undoing, the redo stack is automatically cleared: | ||
|
|
||
| ```javascript | ||
| doc.update((root) => { | ||
| root.value = 1; | ||
| }); | ||
|
|
||
| doc.update((root) => { | ||
| root.value = 2; | ||
| }); | ||
|
|
||
| doc.history.undo(); | ||
| console.log(doc.history.canRedo()); // true | ||
|
|
||
| // Making a new change clears the redo stack | ||
| doc.update((root) => { | ||
| root.value = 3; | ||
| }); | ||
| console.log(doc.history.canRedo()); // false | ||
| ``` | ||
|
|
||
| ##### Supported Operations | ||
|
|
||
| History supports all CRDT types and operations including: | ||
| - **Text**: edit operations (setStyle support is under development) | ||
| - **Object**: property set, delete operations | ||
| - **Array**: push, insert, delete, move operations | ||
| - **Counter**: increase operations | ||
| - **Tree**: Undo/Redo support is under development | ||
|
|
||
| ```javascript | ||
| doc.update((root) => { | ||
| root.todos = []; | ||
| root.todos.push('Task 1'); | ||
| root.todos.push('Task 2'); | ||
| }); | ||
|
|
||
| doc.history.undo(); // Undoes 'Task 2' push | ||
| console.log(doc.getRoot().todos.toJS()); // ['Task 1'] | ||
|
|
||
| doc.history.redo(); // Redoes 'Task 2' push | ||
| console.log(doc.getRoot().todos.toJS()); // ['Task 1', 'Task 2'] | ||
| ``` | ||
|
|
||
|
|
||
|
|
||
| ##### Limitations | ||
|
|
||
| - **Maximum Stack Depth**: The undo/redo stacks maintain a maximum of 50 changes each. Older changes are automatically removed when the limit is reached. | ||
| - **Not Available During Update**: You cannot call `undo()` or `redo()` inside a `doc.update()` callback. | ||
|
|
||
| ```javascript | ||
| doc.update((root) => { | ||
| doc.history.undo(); // ❌ Throws Error: "Undo is not allowed during an update" | ||
| }); | ||
| ``` | ||
|
|
||
| - **Local Only**: History tracks only local changes. Remote changes from other clients are applied but are not added to the undo/redo stacks. This means undo/redo operations only affect your own editing history and seamlessly integrate with changes from other users without conflicts. | ||
|
|
||
| <Alert status="info"> | ||
| When you undo or redo, Yorkie intelligently applies only your changes while preserving modifications made by other collaborators. This ensures conflict-free collaboration where each user can independently manage their own editing history. | ||
| </Alert> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
rg -n --type=ts -C3 'class History\b' .Repository: yorkie-team/yorkie-team.github.io
Length of output: 59
🏁 Script executed:
rg -n --type=ts -C3 '\bundo\s*\(|\bredo\s*\(' .Repository: yorkie-team/yorkie-team.github.io
Length of output: 38575
🏁 Script executed:
# Also let's look at the documentation file to see the exact context
cat -n docs/js-sdk.mdx | sed -n '879,981p'Repository: yorkie-team/yorkie-team.github.io
Length of output: 3935
Tighten wording to align intro and supported ops with actual local-only scope and partial support.
The documentation contradicts itself by claiming undo/redo works for "all document changes" and "all CRDT types," but later specifies it's local-only and some operations are under development (Text.setStyle, Tree). Update the intro and supported operations section to use more precise language:
Suggested wording updates
-Yorkie provides built-in undo/redo functionality for all document changes. This allows users to revert or reapply changes made to the document, making it ideal for collaborative editors and applications requiring change history.
+Yorkie provides built-in undo/redo functionality for local document changes. This allows users to revert or reapply their own changes, making it ideal for collaborative editors and applications requiring change history.
-##### Supported Operations
-History supports all CRDT types and operations including:
+##### Supported Operations
+History currently supports the following CRDT types and operations:🤖 Prompt for AI Agents
In `@docs/js-sdk.mdx` around lines 879 - 981, The intro and Supported Operations
claims are too broad and inconsistent with the local-only and partial-support
notes; update the phrasing around doc.history, doc.history.undo/redo, and the
Supported Operations list (mentioning Text.setStyle and Tree) to explicitly
state history only tracks local changes (not remote), that some features are
experimental/under development (e.g., Text.setStyle, Tree undo/redo), and avoid
saying “all document changes” or “all CRDT types”; keep the examples but add
brief qualifiers where they rely on local operations and mark Text.setStyle and
Tree as not fully supported yet so readers won’t expect global/complete undo
coverage.
What this PR does / why we need it?
Add history functionality to document management
Any background context you want to provide?
What are the relevant tickets?
Fixes #
Checklist
Summary by CodeRabbit