loro-crdt 1.2.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -155,6 +155,36 @@ interface LoroDoc {
155
155
  * ```
156
156
  */
157
157
  subscribeLocalUpdates(f: (bytes: Uint8Array) => void): () => void
158
+ /**
159
+ * Convert the document to a JSON value with a custom replacer function.
160
+ *
161
+ * This method works similarly to `JSON.stringify`'s replacer parameter.
162
+ * The replacer function is called for each value in the document and can transform
163
+ * how values are serialized to JSON.
164
+ *
165
+ * @param replacer - A function that takes a key and value, and returns how that value
166
+ * should be serialized. Similar to JSON.stringify's replacer.
167
+ * If return undefined, the value will be skipped.
168
+ * @returns The JSON representation of the document after applying the replacer function.
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * const doc = new LoroDoc();
173
+ * const text = doc.getText("text");
174
+ * text.insert(0, "Hello");
175
+ * text.mark(0, 2, {bold: true});
176
+ *
177
+ * // Use delta to represent text
178
+ * const json = doc.toJsonWithReplacer((key, value) => {
179
+ * if (value instanceof LoroText) {
180
+ * return value.toDelta();
181
+ * }
182
+ *
183
+ * return value;
184
+ * });
185
+ * ```
186
+ */
187
+ toJsonWithReplacer(replacer: (key: string | index, value: Value | Container) => Value | Container | undefined): Value;
158
188
  }
159
189
 
160
190
  /**
@@ -231,13 +261,14 @@ export type Value =
231
261
  | null
232
262
  | { [key: string]: Value }
233
263
  | Uint8Array
234
- | Value[];
264
+ | Value[]
265
+ | undefined;
235
266
 
236
267
  export type UndoConfig = {
237
268
  mergeInterval?: number,
238
269
  maxUndoSteps?: number,
239
270
  excludeOriginPrefixes?: string[],
240
- onPush?: (isUndo: boolean, counterRange: { start: number, end: number }) => { value: Value, cursors: Cursor[] },
271
+ onPush?: (isUndo: boolean, counterRange: { start: number, end: number }, event?: LoroEventBatch) => { value: Value, cursors: Cursor[] },
241
272
  onPop?: (isUndo: boolean, value: { value: Value, cursors: Cursor[] }, counterRange: { start: number, end: number }) => void
242
273
  };
243
274
  export type Container = LoroList | LoroMap | LoroText | LoroTree | LoroMovableList;
@@ -343,6 +374,15 @@ interface LoroList {
343
374
  getCursor(pos: number, side?: Side): Cursor | undefined;
344
375
  }
345
376
 
377
+ export type TreeNodeShallowValue = {
378
+ id: TreeID,
379
+ parent: TreeID | undefined,
380
+ index: number,
381
+ fractionalIndex: string,
382
+ meta: ContainerID,
383
+ children: TreeNodeShallowValue[],
384
+ }
385
+
346
386
  export type TreeNodeValue = {
347
387
  id: TreeID,
348
388
  parent: TreeID | undefined,
@@ -753,6 +793,14 @@ interface LoroDoc<T extends Record<string, Container> = Record<string, Container
753
793
  */
754
794
  getTree<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroTree ? T[Key] : LoroTree;
755
795
  getText(key: string | ContainerID): LoroText;
796
+ /**
797
+ * Export the updates in the given range.
798
+ *
799
+ * @param start - The start version vector.
800
+ * @param end - The end version vector.
801
+ * @returns The updates in the given range.
802
+ */
803
+ exportJsonUpdates(start?: VersionVector, end?: VersionVector): JsonSchema;
756
804
  }
757
805
  interface LoroList<T = unknown> {
758
806
  new(): LoroList<T>;
@@ -1320,6 +1368,11 @@ export class LoroCounter {
1320
1368
  getAttached(): LoroTree | undefined;
1321
1369
  /**
1322
1370
  * Get the value of the counter.
1371
+ * @returns {number}
1372
+ */
1373
+ getShallowValue(): number;
1374
+ /**
1375
+ * Get the value of the counter.
1323
1376
  */
1324
1377
  readonly value: number;
1325
1378
  }
@@ -1821,13 +1874,6 @@ export class LoroDoc {
1821
1874
  */
1822
1875
  export(mode: ExportMode): Uint8Array;
1823
1876
  /**
1824
- * Export updates in the given range in JSON format.
1825
- * @param {VersionVector | undefined} [start_vv]
1826
- * @param {VersionVector | undefined} [end_vv]
1827
- * @returns {JsonSchema}
1828
- */
1829
- exportJsonUpdates(start_vv?: VersionVector, end_vv?: VersionVector): JsonSchema;
1830
- /**
1831
1877
  * Import updates from the JSON format.
1832
1878
  *
1833
1879
  * only supports backward compatibility but not forward compatibility.
@@ -1863,10 +1909,12 @@ export class LoroDoc {
1863
1909
  */
1864
1910
  import(update_or_snapshot: Uint8Array): ImportStatus;
1865
1911
  /**
1866
- * Import a batch of updates.
1912
+ * Import a batch of updates and snapshots.
1867
1913
  *
1868
1914
  * It's more efficient than importing updates one by one.
1869
1915
  *
1916
+ * @deprecated Use `importBatch` instead.
1917
+ *
1870
1918
  * @example
1871
1919
  * ```ts
1872
1920
  * import { LoroDoc } from "loro-crdt";
@@ -1877,15 +1925,39 @@ export class LoroDoc {
1877
1925
  * const updates = doc.export({ mode: "update" });
1878
1926
  * const snapshot = doc.export({ mode: "snapshot" });
1879
1927
  * const doc2 = new LoroDoc();
1880
- * doc2.importUpdateBatch([snapshot, updates]);
1928
+ * doc2.importBatch([snapshot, updates]);
1881
1929
  * ```
1882
- * @param {Array<any>} data
1930
+ * @param {Uint8Array[]} data
1883
1931
  * @returns {ImportStatus}
1884
1932
  */
1885
- importUpdateBatch(data: Array<any>): ImportStatus;
1933
+ importUpdateBatch(data: Uint8Array[]): ImportStatus;
1934
+ /**
1935
+ * Import a batch of updates or snapshots.
1936
+ *
1937
+ * It's more efficient than importing updates one by one.
1938
+ *
1939
+ * @example
1940
+ * ```ts
1941
+ * import { LoroDoc } from "loro-crdt";
1942
+ *
1943
+ * const doc = new LoroDoc();
1944
+ * const text = doc.getText("text");
1945
+ * text.insert(0, "Hello");
1946
+ * const updates = doc.export({ mode: "update" });
1947
+ * const snapshot = doc.export({ mode: "snapshot" });
1948
+ * const doc2 = new LoroDoc();
1949
+ * doc2.importBatch([snapshot, updates]);
1950
+ * ```
1951
+ * @param {Uint8Array[]} data
1952
+ * @returns {ImportStatus}
1953
+ */
1954
+ importBatch(data: Uint8Array[]): ImportStatus;
1886
1955
  /**
1887
1956
  * Get the shallow json format of the document state.
1888
1957
  *
1958
+ * Unlike `toJSON()` which recursively resolves all containers to their values,
1959
+ * `getShallowValue()` returns container IDs as strings for any nested containers.
1960
+ *
1889
1961
  * @example
1890
1962
  * ```ts
1891
1963
  * import { LoroDoc } from "loro-crdt";
@@ -1895,20 +1967,28 @@ export class LoroDoc {
1895
1967
  * const tree = doc.getTree("tree");
1896
1968
  * const map = doc.getMap("map");
1897
1969
  * const shallowValue = doc.getShallowValue();
1898
- * /*
1899
- * {"list": ..., "tree": ..., "map": ...}
1900
- * *\/
1901
1970
  * console.log(shallowValue);
1971
+ * // {
1972
+ * // list: 'cid:root-list:List',
1973
+ * // tree: 'cid:root-tree:Tree',
1974
+ * // map: 'cid:root-map:Map'
1975
+ * // }
1976
+ *
1977
+ * // It points to the same container as `list`
1978
+ * const listB = doc.getContainerById(shallowValue.list);
1902
1979
  * ```
1903
- * @returns {any}
1980
+ * @returns {Record<string, ContainerID>}
1904
1981
  */
1905
- getShallowValue(): any;
1982
+ getShallowValue(): Record<string, ContainerID>;
1906
1983
  /**
1907
1984
  * Get the json format of the entire document state.
1908
1985
  *
1986
+ * Unlike `getShallowValue()` which returns container IDs as strings,
1987
+ * `toJSON()` recursively resolves all containers to their actual values.
1988
+ *
1909
1989
  * @example
1910
1990
  * ```ts
1911
- * import { LoroDoc, LoroText, LoroMap } from "loro-crdt";
1991
+ * import { LoroDoc, LoroText } from "loro-crdt";
1912
1992
  *
1913
1993
  * const doc = new LoroDoc();
1914
1994
  * const list = doc.getList("list");
@@ -1917,10 +1997,8 @@ export class LoroDoc {
1917
1997
  * text.insert(0, "Hello");
1918
1998
  * const map = list.insertContainer(1, new LoroMap());
1919
1999
  * map.set("foo", "bar");
1920
- * /*
1921
- * {"list": ["Hello", {"foo": "bar"}]}
1922
- * *\/
1923
2000
  * console.log(doc.toJSON());
2001
+ * // {"list": ["Hello", {"foo": "bar"}]}
1924
2002
  * ```
1925
2003
  * @returns {any}
1926
2004
  */
@@ -2181,6 +2259,26 @@ export class LoroList {
2181
2259
  */
2182
2260
  isDeleted(): boolean;
2183
2261
  /**
2262
+ * Get the shallow value of the list.
2263
+ *
2264
+ * Unlike `toJSON()` which recursively resolves all containers to their values,
2265
+ * `getShallowValue()` returns container IDs as strings for any nested containers.
2266
+ *
2267
+ * ```js
2268
+ * const doc = new LoroDoc();
2269
+ * doc.setPeerId("1");
2270
+ * const list = doc.getList("list");
2271
+ * list.insert(0, 1);
2272
+ * list.insert(1, "two");
2273
+ * const subList = list.insertContainer(2, new LoroList());
2274
+ * subList.insert(0, "sub");
2275
+ * list.getShallowValue(); // [1, "two", "cid:2@1:List"]
2276
+ * list.toJSON(); // [1, "two", ["sub"]]
2277
+ * ```
2278
+ * @returns {Value[]}
2279
+ */
2280
+ getShallowValue(): Value[];
2281
+ /**
2184
2282
  * Get the id of this container.
2185
2283
  */
2186
2284
  readonly id: ContainerID;
@@ -2342,6 +2440,34 @@ export class LoroMap {
2342
2440
  */
2343
2441
  isDeleted(): boolean;
2344
2442
  /**
2443
+ * Get the shallow value of the map.
2444
+ *
2445
+ * Unlike `toJSON()` which recursively resolves all containers to their values,
2446
+ * `getShallowValue()` returns container IDs as strings for any nested containers.
2447
+ *
2448
+ * @example
2449
+ * ```ts
2450
+ * import { LoroDoc } from "loro-crdt";
2451
+ *
2452
+ * const doc = new LoroDoc();
2453
+ * doc.setPeerId("1");
2454
+ * const map = doc.getMap("map");
2455
+ * map.set("key", "value");
2456
+ * const subText = map.setContainer("text", new LoroText());
2457
+ * subText.insert(0, "Hello");
2458
+ *
2459
+ * // Get shallow value - nested containers are represented by their IDs
2460
+ * console.log(map.getShallowValue());
2461
+ * // Output: { key: "value", text: "cid:1@1:Text" }
2462
+ *
2463
+ * // Get full value with nested containers resolved by `toJSON()`
2464
+ * console.log(map.toJSON());
2465
+ * // Output: { key: "value", text: "Hello" }
2466
+ * ```
2467
+ * @returns {Record<string, Value>}
2468
+ */
2469
+ getShallowValue(): Record<string, Value>;
2470
+ /**
2345
2471
  * The container id of this handler.
2346
2472
  */
2347
2473
  readonly id: ContainerID;
@@ -2485,6 +2611,26 @@ export class LoroMovableList {
2485
2611
  */
2486
2612
  isDeleted(): boolean;
2487
2613
  /**
2614
+ * Get the shallow value of the movable list.
2615
+ *
2616
+ * Unlike `toJSON()` which recursively resolves all containers to their values,
2617
+ * `getShallowValue()` returns container IDs as strings for any nested containers.
2618
+ *
2619
+ * ```js
2620
+ * const doc = new LoroDoc();
2621
+ * doc.setPeerId("1");
2622
+ * const list = doc.getMovableList("list");
2623
+ * list.insert(0, 1);
2624
+ * list.insert(1, "two");
2625
+ * const subList = list.insertContainer(2, new LoroList());
2626
+ * subList.insert(0, "sub");
2627
+ * list.getShallowValue(); // [1, "two", "cid:2@1:List"]
2628
+ * list.toJSON(); // [1, "two", ["sub"]]
2629
+ * ```
2630
+ * @returns {Value[]}
2631
+ */
2632
+ getShallowValue(): Value[];
2633
+ /**
2488
2634
  * Get the id of this container.
2489
2635
  */
2490
2636
  readonly id: ContainerID;
@@ -2800,6 +2946,11 @@ export class LoroText {
2800
2946
  */
2801
2947
  isDeleted(): boolean;
2802
2948
  /**
2949
+ * Get the shallow value of the text. This equals to `text.toString()`.
2950
+ * @returns {string}
2951
+ */
2952
+ getShallowValue(): string;
2953
+ /**
2803
2954
  * Get the container id of the text.
2804
2955
  */
2805
2956
  readonly id: ContainerID;
@@ -2972,6 +3123,48 @@ export class LoroTree {
2972
3123
  */
2973
3124
  isDeleted(): boolean;
2974
3125
  /**
3126
+ * Get the shallow value of the tree.
3127
+ *
3128
+ * Unlike `toJSON()` which recursively resolves nested containers to their values,
3129
+ * `getShallowValue()` returns container IDs as strings for any nested containers.
3130
+ *
3131
+ * @example
3132
+ * ```ts
3133
+ * const doc = new LoroDoc();
3134
+ * doc.setPeerId("1");
3135
+ * const tree = doc.getTree("tree");
3136
+ * const root = tree.createNode();
3137
+ * root.data.set("name", "root");
3138
+ * const text = root.data.setContainer("content", new LoroText());
3139
+ * text.insert(0, "Hello");
3140
+ *
3141
+ * console.log(tree.getShallowValue());
3142
+ * // [{
3143
+ * // id: "0@1",
3144
+ * // parent: null,
3145
+ * // index: 0,
3146
+ * // fractional_index: "80",
3147
+ * // meta: "cid:0@1:Map",
3148
+ * // children: []
3149
+ * // }]
3150
+ *
3151
+ * console.log(tree.toJSON());
3152
+ * // [{
3153
+ * // id: "0@1",
3154
+ * // parent: null,
3155
+ * // index: 0,
3156
+ * // fractional_index: "80",
3157
+ * // meta: {
3158
+ * // name: "root",
3159
+ * // content: "Hello"
3160
+ * // },
3161
+ * // children: []
3162
+ * // }]
3163
+ * ```
3164
+ * @returns {TreeNodeShallowValue[]}
3165
+ */
3166
+ getShallowValue(): TreeNodeShallowValue[];
3167
+ /**
2975
3168
  * Get the id of the container.
2976
3169
  */
2977
3170
  readonly id: ContainerID;