| @loro-extended/change | major |
|---|---|
| @loro-extended/repo | major |
| @loro-extended/react | major |
| @loro-extended/hooks-core | major |
This release introduces significant breaking changes to simplify the loro-extended API. The changes consolidate mutation patterns, simplify native Loro access, and remove redundant APIs.
Handle.change()removed - Usechange(handle.doc, fn)insteadloro()now returns native types directly - No more.docor.containerindirectionext(ref).change()removed - Usechange(ref, fn)insteadgetLoroDoc()removed - Useloro(doc)insteadloro(ref).docremoved - Useext(ref).docinsteadloro(ref).containerremoved - Useloro(ref)directly
The Handle.change() method has been removed from @loro-extended/repo to narrow its focus as a handle. Use the change() functional helper instead.
Before:
handle.change((draft) => {
draft.title.insert(0, "Hello");
draft.count.increment(5);
});After:
import { change } from "@loro-extended/change";
change(handle.doc, (draft) => {
draft.title.insert(0, "Hello");
draft.count.increment(5);
});The loro() function now returns native Loro types directly, without the .doc or .container indirection.
Before:
// For TypedDoc
const loroDoc = loro(doc).doc;
const frontiers = loro(doc).doc.frontiers();
loro(doc).doc.subscribe(callback);
loro(doc).doc.import(bytes);
// For TypedRef
const loroText = loro(textRef).container;
const loroList = loro(listRef).container;After:
// For TypedDoc - loro() returns LoroDoc directly
const loroDoc = loro(doc);
const frontiers = loro(doc).frontiers();
loro(doc).subscribe(callback);
loro(doc).import(bytes);
// For TypedRef - loro() returns the container directly
const loroText = loro(textRef); // Returns LoroText
const loroList = loro(listRef); // Returns LoroListThe change() method has been deprecated from the loro() namespace for refs. Use the change() functional helper instead.
Before:
loro(ref).change((draft) => {
// mutations
});After:
import { change } from "@loro-extended/change";
change(ref, (draft) => {
// mutations
});The getLoroDoc() function has been removed. Use loro(doc) directly.
Before:
import { getLoroDoc } from "@loro-extended/change";
const loroDoc = getLoroDoc(typedDoc);After:
import { loro } from "@loro-extended/change";
const loroDoc = loro(typedDoc);To get the underlying LoroDoc from a ref, use ext(ref).doc instead of loro(ref).doc. This belongs on ext() because loro's native containers don't point back to their LoroDoc.
Before:
const loroDoc = loro(textRef).doc;After:
import { ext } from "@loro-extended/change";
const loroDoc = ext(textRef).doc;-
Update imports:
// Add these imports where needed import { change, loro, ext } from "@loro-extended/change";
-
Replace
handle.change(fn)withchange(handle.doc, fn):# Find all usages grep -r "handle\.change(" --include="*.ts" --include="*.tsx"
-
Replace
loro(x).docwithloro(x):# Find all usages grep -r "loro(.*).doc" --include="*.ts" --include="*.tsx"
-
Replace
loro(ref).containerwithloro(ref):# Find all usages grep -r "loro(.*).container" --include="*.ts" --include="*.tsx"
-
Replace
getLoroDoc(x)withloro(x):# Find all usages grep -r "getLoroDoc(" --include="*.ts" --include="*.tsx"
-
Replace
loro(ref).docwithext(ref).doc:# For refs (not docs), use ext() to access the LoroDoc # Before: loro(textRef).doc # After: ext(textRef).doc
| Old Pattern | New Pattern |
|---|---|
handle.change(fn) |
change(handle.doc, fn) |
loro(doc).doc |
loro(doc) |
loro(doc).doc.frontiers() |
loro(doc).frontiers() |
loro(doc).doc.subscribe(cb) |
loro(doc).subscribe(cb) |
loro(doc).doc.import(bytes) |
loro(doc).import(bytes) |
loro(doc).doc.export(opts) |
loro(doc).export(opts) |
loro(ref).container |
loro(ref) |
loro(ref).doc |
ext(ref).doc |
getLoroDoc(doc) |
loro(doc) |
ext(ref).change(fn) |
change(ref, fn) |
The change(doc, fn) functional helper is the canonical way to mutate documents:
import { change } from "@loro-extended/change";
// Mutate a TypedDoc
change(doc, (draft) => {
draft.title.insert(0, "Hello");
draft.count.increment(5);
draft.items.push("new item");
});
// Mutate via a Handle
change(handle.doc, (draft) => {
draft.title.insert(0, "Hello");
});Note: ext(doc).change(fn) is also available for method-chaining scenarios, but change(doc, fn) is preferred.
Use loro() to access native Loro types:
import { loro } from "@loro-extended/change";
// Get LoroDoc from TypedDoc
const loroDoc = loro(doc);
const frontiers = loro(doc).frontiers();
const version = loro(doc).version();
// Get native containers from refs
const loroText: LoroText = loro(doc.title);
const loroList: LoroList = loro(doc.items);
const loroCounter: LoroCounter = loro(doc.count);Use ext() for loro-extended-specific features:
import { ext } from "@loro-extended/change";
// Document-level features
ext(doc).fork(); // Fork the TypedDoc
ext(doc).forkAt(frontiers); // Fork TypedDoc at specific version
ext(doc).shallowForkAt(frontiers); // Shallow fork of TypedDoc
ext(doc).initialize(); // Initialize metadata
ext(doc).applyPatch(patch); // Apply JSON patch
ext(doc).docShape; // Get the schema
ext(doc).rawValue; // Get raw JSON value, no overlay or diff
ext(doc).mergeable; // Check mergeable flag
// Ref-level features
ext(ref).doc; // Get LoroDoc from any ref
ext(listRef).pushContainer(c); // Push container to list
ext(listRef).insertContainer(i, c); // Insert container at index
ext(mapRef).setContainer(key, c); // Set container on map
// Subscriptions via subscribe() functional helper
subscribe(doc, callback); // Subscribe to all document changes
subscribe(doc, p => p.config.theme, callback); // Subscribe to specific path
subscribe(ref, callback); // Subscribe to container changes
// Or use loro() for native Loro subscription access
loro(doc).subscribe(callback); // Native LoroDoc subscriptionThese changes simplify the API by:
- Consolidating mutation patterns - One canonical way to mutate:
change(doc, fn) - Removing indirection -
loro()returns native types directly, no.docor.container - Clear separation -
loro()for native Loro access,ext()for loro-extended features - Reducing cognitive load - Fewer ways to do the same thing
The previous API had multiple ways to mutate documents (handle.change(), ext(doc).change(), change(doc, fn)) and required extra property access to get native types (loro(doc).doc). The new API is more consistent and easier to learn.