loro-crdt 1.0.7 → 1.0.8-alpha.1
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.
- package/CHANGELOG.md +739 -0
- package/LICENSE +12 -13
- package/README.md +55 -50
- package/bundler/index.d.ts +72 -0
- package/bundler/index.js +156 -0
- package/bundler/index.js.map +1 -0
- package/bundler/loro_wasm.d.ts +3103 -0
- package/bundler/loro_wasm.js +16 -0
- package/bundler/loro_wasm_bg.js +5886 -0
- package/bundler/loro_wasm_bg.wasm +0 -0
- package/bundler/loro_wasm_bg.wasm.d.ts +249 -0
- package/deno_tests/.vscode/settings.json +3 -0
- package/deno_tests/basic.test.ts +10 -0
- package/deno_tests/deno.json +3 -0
- package/nodejs/index.js +169 -0
- package/nodejs/index.js.map +1 -0
- package/nodejs/loro_wasm.d.ts +3103 -0
- package/nodejs/loro_wasm.js +5915 -0
- package/nodejs/loro_wasm_bg.wasm +0 -0
- package/nodejs/loro_wasm_bg.wasm.d.ts +249 -0
- package/package.json +17 -28
- package/ts/index.ts +216 -0
- package/web/index.d.ts +72 -0
- package/web/index.js +156 -0
- package/web/index.js.map +1 -0
- package/web/loro_wasm.d.ts +3376 -0
- package/web/loro_wasm.js +5864 -0
- package/web/loro_wasm_bg.wasm +0 -0
- package/web/loro_wasm_bg.wasm.d.ts +249 -0
- package/dist/loro.d.ts +0 -595
- package/dist/loro.js +0 -129
- package/dist/loro.js.map +0 -1
- package/dist/loro.mjs +0 -116
- package/dist/loro.mjs.map +0 -1
|
@@ -0,0 +1,3376 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/**
|
|
4
|
+
*/
|
|
5
|
+
export function run(): void;
|
|
6
|
+
/**
|
|
7
|
+
* @param {({ peer: PeerID, counter: number })[]} frontiers
|
|
8
|
+
* @returns {Uint8Array}
|
|
9
|
+
*/
|
|
10
|
+
export function encodeFrontiers(frontiers: ({ peer: PeerID, counter: number })[]): Uint8Array;
|
|
11
|
+
/**
|
|
12
|
+
* @param {Uint8Array} bytes
|
|
13
|
+
* @returns {{ peer: PeerID, counter: number }[]}
|
|
14
|
+
*/
|
|
15
|
+
export function decodeFrontiers(bytes: Uint8Array): { peer: PeerID, counter: number }[];
|
|
16
|
+
/**
|
|
17
|
+
* Enable debug info of Loro
|
|
18
|
+
*/
|
|
19
|
+
export function setDebug(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Decode the metadata of the import blob.
|
|
22
|
+
*
|
|
23
|
+
* This method is useful to get the following metadata of the import blob:
|
|
24
|
+
*
|
|
25
|
+
* - startVersionVector
|
|
26
|
+
* - endVersionVector
|
|
27
|
+
* - startTimestamp
|
|
28
|
+
* - endTimestamp
|
|
29
|
+
* - isSnapshot
|
|
30
|
+
* - changeNum
|
|
31
|
+
* @param {Uint8Array} blob
|
|
32
|
+
* @returns {ImportBlobMetadata}
|
|
33
|
+
*/
|
|
34
|
+
export function decodeImportBlobMeta(blob: Uint8Array): ImportBlobMetadata;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Container types supported by loro.
|
|
38
|
+
*
|
|
39
|
+
* It is most commonly used to specify the type of sub-container to be created.
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
43
|
+
*
|
|
44
|
+
* const doc = new LoroDoc();
|
|
45
|
+
* const list = doc.getList("list");
|
|
46
|
+
* list.insert(0, 100);
|
|
47
|
+
* const text = list.insertContainer(1, new LoroText());
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export type ContainerType = "Text" | "Map" | "List"| "Tree" | "MovableList";
|
|
51
|
+
|
|
52
|
+
export type PeerID = `${number}`;
|
|
53
|
+
/**
|
|
54
|
+
* The unique id of each container.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { LoroDoc } from "loro-crdt";
|
|
59
|
+
*
|
|
60
|
+
* const doc = new LoroDoc();
|
|
61
|
+
* const list = doc.getList("list");
|
|
62
|
+
* const containerId = list.id;
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export type ContainerID =
|
|
66
|
+
| `cid:root-${string}:${ContainerType}`
|
|
67
|
+
| `cid:${number}@${PeerID}:${ContainerType}`;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The unique id of each tree node.
|
|
71
|
+
*/
|
|
72
|
+
export type TreeID = `${number}@${PeerID}`;
|
|
73
|
+
|
|
74
|
+
interface LoroDoc {
|
|
75
|
+
/**
|
|
76
|
+
* Export updates from the specific version to the current version
|
|
77
|
+
*
|
|
78
|
+
* @deprecated Use `export({mode: "update", from: version})` instead
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* import { LoroDoc } from "loro-crdt";
|
|
83
|
+
*
|
|
84
|
+
* const doc = new LoroDoc();
|
|
85
|
+
* const text = doc.getText("text");
|
|
86
|
+
* text.insert(0, "Hello");
|
|
87
|
+
* // get all updates of the doc
|
|
88
|
+
* const updates = doc.exportFrom();
|
|
89
|
+
* const version = doc.oplogVersion();
|
|
90
|
+
* text.insert(5, " World");
|
|
91
|
+
* // get updates from specific version to the latest version
|
|
92
|
+
* const updates2 = doc.exportFrom(version);
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
exportFrom(version?: VersionVector): Uint8Array;
|
|
96
|
+
/**
|
|
97
|
+
*
|
|
98
|
+
* Get the container corresponding to the container id
|
|
99
|
+
*
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { LoroDoc } from "loro-crdt";
|
|
104
|
+
*
|
|
105
|
+
* const doc = new LoroDoc();
|
|
106
|
+
* let text = doc.getText("text");
|
|
107
|
+
* const textId = text.id;
|
|
108
|
+
* text = doc.getContainerById(textId);
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
getContainerById(id: ContainerID): Container;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Subscribe to updates from local edits.
|
|
115
|
+
*
|
|
116
|
+
* This method allows you to listen for local changes made to the document.
|
|
117
|
+
* It's useful for syncing changes with other instances or saving updates.
|
|
118
|
+
*
|
|
119
|
+
* @param f - A callback function that receives a Uint8Array containing the update data.
|
|
120
|
+
* @returns A function to unsubscribe from the updates.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* const loro = new Loro();
|
|
125
|
+
* const text = loro.getText("text");
|
|
126
|
+
*
|
|
127
|
+
* const unsubscribe = loro.subscribeLocalUpdates((update) => {
|
|
128
|
+
* console.log("Local update received:", update);
|
|
129
|
+
* // You can send this update to other Loro instances
|
|
130
|
+
* });
|
|
131
|
+
*
|
|
132
|
+
* text.insert(0, "Hello");
|
|
133
|
+
* loro.commit();
|
|
134
|
+
*
|
|
135
|
+
* // Later, when you want to stop listening:
|
|
136
|
+
* unsubscribe();
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* const loro1 = new Loro();
|
|
142
|
+
* const loro2 = new Loro();
|
|
143
|
+
*
|
|
144
|
+
* // Set up two-way sync
|
|
145
|
+
* loro1.subscribeLocalUpdates((updates) => {
|
|
146
|
+
* loro2.import(updates);
|
|
147
|
+
* });
|
|
148
|
+
*
|
|
149
|
+
* loro2.subscribeLocalUpdates((updates) => {
|
|
150
|
+
* loro1.import(updates);
|
|
151
|
+
* });
|
|
152
|
+
*
|
|
153
|
+
* // Now changes in loro1 will be reflected in loro2 and vice versa
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
subscribeLocalUpdates(f: (bytes: Uint8Array) => void): () => void
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Represents a `Delta` type which is a union of different operations that can be performed.
|
|
161
|
+
*
|
|
162
|
+
* @typeparam T - The data type for the `insert` operation.
|
|
163
|
+
*
|
|
164
|
+
* The `Delta` type can be one of three distinct shapes:
|
|
165
|
+
*
|
|
166
|
+
* 1. Insert Operation:
|
|
167
|
+
* - `insert`: The item to be inserted, of type T.
|
|
168
|
+
* - `attributes`: (Optional) A dictionary of attributes, describing styles in richtext
|
|
169
|
+
*
|
|
170
|
+
* 2. Delete Operation:
|
|
171
|
+
* - `delete`: The number of elements to delete.
|
|
172
|
+
*
|
|
173
|
+
* 3. Retain Operation:
|
|
174
|
+
* - `retain`: The number of elements to retain.
|
|
175
|
+
* - `attributes`: (Optional) A dictionary of attributes, describing styles in richtext
|
|
176
|
+
*/
|
|
177
|
+
export type Delta<T> =
|
|
178
|
+
| {
|
|
179
|
+
insert: T;
|
|
180
|
+
attributes?: { [key in string]: {} };
|
|
181
|
+
retain?: undefined;
|
|
182
|
+
delete?: undefined;
|
|
183
|
+
}
|
|
184
|
+
| {
|
|
185
|
+
delete: number;
|
|
186
|
+
attributes?: undefined;
|
|
187
|
+
retain?: undefined;
|
|
188
|
+
insert?: undefined;
|
|
189
|
+
}
|
|
190
|
+
| {
|
|
191
|
+
retain: number;
|
|
192
|
+
attributes?: { [key in string]: {} };
|
|
193
|
+
delete?: undefined;
|
|
194
|
+
insert?: undefined;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The unique id of each operation.
|
|
199
|
+
*/
|
|
200
|
+
export type OpId = { peer: PeerID, counter: number };
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Change is a group of continuous operations
|
|
204
|
+
*/
|
|
205
|
+
export interface Change {
|
|
206
|
+
peer: PeerID,
|
|
207
|
+
counter: number,
|
|
208
|
+
lamport: number,
|
|
209
|
+
length: number,
|
|
210
|
+
/**
|
|
211
|
+
* The timestamp in seconds.
|
|
212
|
+
*
|
|
213
|
+
* [Unix time](https://en.wikipedia.org/wiki/Unix_time)
|
|
214
|
+
* It is the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970.
|
|
215
|
+
*/
|
|
216
|
+
timestamp: number,
|
|
217
|
+
deps: OpId[],
|
|
218
|
+
message: string | undefined,
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Data types supported by loro
|
|
224
|
+
*/
|
|
225
|
+
export type Value =
|
|
226
|
+
| ContainerID
|
|
227
|
+
| string
|
|
228
|
+
| number
|
|
229
|
+
| boolean
|
|
230
|
+
| null
|
|
231
|
+
| { [key: string]: Value }
|
|
232
|
+
| Uint8Array
|
|
233
|
+
| Value[];
|
|
234
|
+
|
|
235
|
+
export type UndoConfig = {
|
|
236
|
+
mergeInterval?: number,
|
|
237
|
+
maxUndoSteps?: number,
|
|
238
|
+
excludeOriginPrefixes?: string[],
|
|
239
|
+
onPush?: (isUndo: boolean, counterRange: { start: number, end: number }) => { value: Value, cursors: Cursor[] },
|
|
240
|
+
onPop?: (isUndo: boolean, value: { value: Value, cursors: Cursor[] }, counterRange: { start: number, end: number }) => void
|
|
241
|
+
};
|
|
242
|
+
export type Container = LoroList | LoroMap | LoroText | LoroTree | LoroMovableList;
|
|
243
|
+
|
|
244
|
+
export interface ImportBlobMetadata {
|
|
245
|
+
/**
|
|
246
|
+
* The version vector of the start of the import.
|
|
247
|
+
*
|
|
248
|
+
* Import blob includes all the ops from `partial_start_vv` to `partial_end_vv`.
|
|
249
|
+
* However, it does not constitute a complete version vector, as it only contains counters
|
|
250
|
+
* from peers included within the import blob.
|
|
251
|
+
*/
|
|
252
|
+
partialStartVersionVector: VersionVector;
|
|
253
|
+
/**
|
|
254
|
+
* The version vector of the end of the import.
|
|
255
|
+
*
|
|
256
|
+
* Import blob includes all the ops from `partial_start_vv` to `partial_end_vv`.
|
|
257
|
+
* However, it does not constitute a complete version vector, as it only contains counters
|
|
258
|
+
* from peers included within the import blob.
|
|
259
|
+
*/
|
|
260
|
+
partialEndVersionVector: VersionVector;
|
|
261
|
+
|
|
262
|
+
startFrontiers: OpId[],
|
|
263
|
+
startTimestamp: number;
|
|
264
|
+
endTimestamp: number;
|
|
265
|
+
isSnapshot: boolean;
|
|
266
|
+
changeNum: number;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
interface LoroText {
|
|
270
|
+
/**
|
|
271
|
+
* Get the cursor position at the given pos.
|
|
272
|
+
*
|
|
273
|
+
* When expressing the position of a cursor, using "index" can be unstable
|
|
274
|
+
* because the cursor's position may change due to other deletions and insertions,
|
|
275
|
+
* requiring updates with each edit. To stably represent a position or range within
|
|
276
|
+
* a list structure, we can utilize the ID of each item/character on List CRDT or
|
|
277
|
+
* Text CRDT for expression.
|
|
278
|
+
*
|
|
279
|
+
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
|
|
280
|
+
* approach complicates tracking cursors since they rely on these IDs. The solution
|
|
281
|
+
* recalculates position by replaying relevant history to update cursors
|
|
282
|
+
* accurately. To minimize the performance impact of history replay, the system
|
|
283
|
+
* updates cursor info to reference only the IDs of currently present elements,
|
|
284
|
+
* thereby reducing the need for replay.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```ts
|
|
288
|
+
*
|
|
289
|
+
* const doc = new LoroDoc();
|
|
290
|
+
* const text = doc.getText("text");
|
|
291
|
+
* text.insert(0, "123");
|
|
292
|
+
* const pos0 = text.getCursor(0, 0);
|
|
293
|
+
* {
|
|
294
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
295
|
+
* expect(ans.offset).toBe(0);
|
|
296
|
+
* }
|
|
297
|
+
* text.insert(0, "1");
|
|
298
|
+
* {
|
|
299
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
300
|
+
* expect(ans.offset).toBe(1);
|
|
301
|
+
* }
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
getCursor(pos: number, side?: Side): Cursor | undefined;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
interface LoroList {
|
|
308
|
+
/**
|
|
309
|
+
* Get the cursor position at the given pos.
|
|
310
|
+
*
|
|
311
|
+
* When expressing the position of a cursor, using "index" can be unstable
|
|
312
|
+
* because the cursor's position may change due to other deletions and insertions,
|
|
313
|
+
* requiring updates with each edit. To stably represent a position or range within
|
|
314
|
+
* a list structure, we can utilize the ID of each item/character on List CRDT or
|
|
315
|
+
* Text CRDT for expression.
|
|
316
|
+
*
|
|
317
|
+
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
|
|
318
|
+
* approach complicates tracking cursors since they rely on these IDs. The solution
|
|
319
|
+
* recalculates position by replaying relevant history to update cursors
|
|
320
|
+
* accurately. To minimize the performance impact of history replay, the system
|
|
321
|
+
* updates cursor info to reference only the IDs of currently present elements,
|
|
322
|
+
* thereby reducing the need for replay.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```ts
|
|
326
|
+
*
|
|
327
|
+
* const doc = new LoroDoc();
|
|
328
|
+
* const text = doc.getList("list");
|
|
329
|
+
* text.insert(0, "1");
|
|
330
|
+
* const pos0 = text.getCursor(0, 0);
|
|
331
|
+
* {
|
|
332
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
333
|
+
* expect(ans.offset).toBe(0);
|
|
334
|
+
* }
|
|
335
|
+
* text.insert(0, "1");
|
|
336
|
+
* {
|
|
337
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
338
|
+
* expect(ans.offset).toBe(1);
|
|
339
|
+
* }
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
getCursor(pos: number, side?: Side): Cursor | undefined;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export type TreeNodeValue = {
|
|
346
|
+
id: TreeID,
|
|
347
|
+
parent: TreeID | undefined,
|
|
348
|
+
index: number,
|
|
349
|
+
fractionalIndex: string,
|
|
350
|
+
meta: LoroMap,
|
|
351
|
+
children: TreeNodeValue[],
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
interface LoroTree{
|
|
355
|
+
toArray(): TreeNodeValue[];
|
|
356
|
+
getNodes(options?: { withDeleted: boolean = false }): LoroTreeNode[];
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
interface LoroMovableList {
|
|
360
|
+
/**
|
|
361
|
+
* Get the cursor position at the given pos.
|
|
362
|
+
*
|
|
363
|
+
* When expressing the position of a cursor, using "index" can be unstable
|
|
364
|
+
* because the cursor's position may change due to other deletions and insertions,
|
|
365
|
+
* requiring updates with each edit. To stably represent a position or range within
|
|
366
|
+
* a list structure, we can utilize the ID of each item/character on List CRDT or
|
|
367
|
+
* Text CRDT for expression.
|
|
368
|
+
*
|
|
369
|
+
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
|
|
370
|
+
* approach complicates tracking cursors since they rely on these IDs. The solution
|
|
371
|
+
* recalculates position by replaying relevant history to update cursors
|
|
372
|
+
* accurately. To minimize the performance impact of history replay, the system
|
|
373
|
+
* updates cursor info to reference only the IDs of currently present elements,
|
|
374
|
+
* thereby reducing the need for replay.
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```ts
|
|
378
|
+
*
|
|
379
|
+
* const doc = new LoroDoc();
|
|
380
|
+
* const text = doc.getMovableList("text");
|
|
381
|
+
* text.insert(0, "1");
|
|
382
|
+
* const pos0 = text.getCursor(0, 0);
|
|
383
|
+
* {
|
|
384
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
385
|
+
* expect(ans.offset).toBe(0);
|
|
386
|
+
* }
|
|
387
|
+
* text.insert(0, "1");
|
|
388
|
+
* {
|
|
389
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
390
|
+
* expect(ans.offset).toBe(1);
|
|
391
|
+
* }
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
394
|
+
getCursor(pos: number, side?: Side): Cursor | undefined;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export type Side = -1 | 0 | 1;
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
export type JsonOpID = `${number}@${PeerID}`;
|
|
402
|
+
export type JsonContainerID = `🦜:${ContainerID}` ;
|
|
403
|
+
export type JsonValue =
|
|
404
|
+
| JsonContainerID
|
|
405
|
+
| string
|
|
406
|
+
| number
|
|
407
|
+
| boolean
|
|
408
|
+
| null
|
|
409
|
+
| { [key: string]: JsonValue }
|
|
410
|
+
| Uint8Array
|
|
411
|
+
| JsonValue[];
|
|
412
|
+
|
|
413
|
+
export type JsonSchema = {
|
|
414
|
+
schema_version: number;
|
|
415
|
+
start_version: Map<string, number>,
|
|
416
|
+
peers: PeerID[],
|
|
417
|
+
changes: JsonChange[]
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
export type JsonChange = {
|
|
421
|
+
id: JsonOpID
|
|
422
|
+
/**
|
|
423
|
+
* The timestamp in seconds.
|
|
424
|
+
*
|
|
425
|
+
* [Unix time](https://en.wikipedia.org/wiki/Unix_time)
|
|
426
|
+
* It is the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970.
|
|
427
|
+
*/
|
|
428
|
+
timestamp: number,
|
|
429
|
+
deps: JsonOpID[],
|
|
430
|
+
lamport: number,
|
|
431
|
+
msg: string | null,
|
|
432
|
+
ops: JsonOp[]
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export type ExportMode = {
|
|
436
|
+
mode: "update",
|
|
437
|
+
from?: VersionVector,
|
|
438
|
+
} | {
|
|
439
|
+
mode: "snapshot",
|
|
440
|
+
} | {
|
|
441
|
+
mode: "shallow-snapshot",
|
|
442
|
+
frontiers: Frontiers,
|
|
443
|
+
} | {
|
|
444
|
+
mode: "updates-in-range",
|
|
445
|
+
spans: {
|
|
446
|
+
id: ID,
|
|
447
|
+
len: number,
|
|
448
|
+
}[],
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
export type JsonOp = {
|
|
452
|
+
container: ContainerID,
|
|
453
|
+
counter: number,
|
|
454
|
+
content: ListOp | TextOp | MapOp | TreeOp | MovableListOp | UnknownOp
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export type ListOp = {
|
|
458
|
+
type: "insert",
|
|
459
|
+
pos: number,
|
|
460
|
+
value: JsonValue
|
|
461
|
+
} | {
|
|
462
|
+
type: "delete",
|
|
463
|
+
pos: number,
|
|
464
|
+
len: number,
|
|
465
|
+
start_id: JsonOpID,
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
export type MovableListOp = {
|
|
469
|
+
type: "insert",
|
|
470
|
+
pos: number,
|
|
471
|
+
value: JsonValue
|
|
472
|
+
} | {
|
|
473
|
+
type: "delete",
|
|
474
|
+
pos: number,
|
|
475
|
+
len: number,
|
|
476
|
+
start_id: JsonOpID,
|
|
477
|
+
}| {
|
|
478
|
+
type: "move",
|
|
479
|
+
from: number,
|
|
480
|
+
to: number,
|
|
481
|
+
elem_id: JsonOpID,
|
|
482
|
+
}|{
|
|
483
|
+
type: "set",
|
|
484
|
+
elem_id: JsonOpID,
|
|
485
|
+
value: JsonValue
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export type TextOp = {
|
|
489
|
+
type: "insert",
|
|
490
|
+
pos: number,
|
|
491
|
+
text: string
|
|
492
|
+
} | {
|
|
493
|
+
type: "delete",
|
|
494
|
+
pos: number,
|
|
495
|
+
len: number,
|
|
496
|
+
start_id: JsonOpID,
|
|
497
|
+
} | {
|
|
498
|
+
type: "mark",
|
|
499
|
+
start: number,
|
|
500
|
+
end: number,
|
|
501
|
+
style_key: string,
|
|
502
|
+
style_value: JsonValue,
|
|
503
|
+
info: number
|
|
504
|
+
}|{
|
|
505
|
+
type: "mark_end"
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
export type MapOp = {
|
|
509
|
+
type: "insert",
|
|
510
|
+
key: string,
|
|
511
|
+
value: JsonValue
|
|
512
|
+
} | {
|
|
513
|
+
type: "delete",
|
|
514
|
+
key: string,
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
export type TreeOp = {
|
|
518
|
+
type: "create",
|
|
519
|
+
target: TreeID,
|
|
520
|
+
parent: TreeID | undefined,
|
|
521
|
+
fractional_index: string
|
|
522
|
+
}|{
|
|
523
|
+
type: "move",
|
|
524
|
+
target: TreeID,
|
|
525
|
+
parent: TreeID | undefined,
|
|
526
|
+
fractional_index: string
|
|
527
|
+
}|{
|
|
528
|
+
type: "delete",
|
|
529
|
+
target: TreeID
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
export type UnknownOp = {
|
|
533
|
+
type: "unknown"
|
|
534
|
+
prop: number,
|
|
535
|
+
value_type: "unknown",
|
|
536
|
+
value: {
|
|
537
|
+
kind: number,
|
|
538
|
+
data: Uint8Array
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
export type CounterSpan = { start: number, end: number };
|
|
543
|
+
|
|
544
|
+
export type ImportStatus = {
|
|
545
|
+
success: Map<PeerID, CounterSpan>,
|
|
546
|
+
pending: Map<PeerID, CounterSpan> | null
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
export type Frontiers = OpId[];
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Represents a path to identify the exact location of an event's target.
|
|
553
|
+
* The path is composed of numbers (e.g., indices of a list container) strings
|
|
554
|
+
* (e.g., keys of a map container) and TreeID (the node of a tree container),
|
|
555
|
+
* indicating the absolute position of the event's source within a loro document.
|
|
556
|
+
*/
|
|
557
|
+
export type Path = (number | string | TreeID)[];
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* A batch of events that created by a single `import`/`transaction`/`checkout`.
|
|
561
|
+
*
|
|
562
|
+
* @prop by - How the event is triggered.
|
|
563
|
+
* @prop origin - (Optional) Provides information about the origin of the event.
|
|
564
|
+
* @prop diff - Contains the differential information related to the event.
|
|
565
|
+
* @prop target - Identifies the container ID of the event's target.
|
|
566
|
+
* @prop path - Specifies the absolute path of the event's emitter, which can be an index of a list container or a key of a map container.
|
|
567
|
+
*/
|
|
568
|
+
export interface LoroEventBatch {
|
|
569
|
+
/**
|
|
570
|
+
* How the event is triggered.
|
|
571
|
+
*
|
|
572
|
+
* - `local`: The event is triggered by a local transaction.
|
|
573
|
+
* - `import`: The event is triggered by an import operation.
|
|
574
|
+
* - `checkout`: The event is triggered by a checkout operation.
|
|
575
|
+
*/
|
|
576
|
+
by: "local" | "import" | "checkout";
|
|
577
|
+
origin?: string;
|
|
578
|
+
/**
|
|
579
|
+
* The container ID of the current event receiver.
|
|
580
|
+
* It's undefined if the subscriber is on the root document.
|
|
581
|
+
*/
|
|
582
|
+
currentTarget?: ContainerID;
|
|
583
|
+
events: LoroEvent[];
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* The concrete event of Loro.
|
|
588
|
+
*/
|
|
589
|
+
export interface LoroEvent {
|
|
590
|
+
/**
|
|
591
|
+
* The container ID of the event's target.
|
|
592
|
+
*/
|
|
593
|
+
target: ContainerID;
|
|
594
|
+
diff: Diff;
|
|
595
|
+
/**
|
|
596
|
+
* The absolute path of the event's emitter, which can be an index of a list container or a key of a map container.
|
|
597
|
+
*/
|
|
598
|
+
path: Path;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export type ListDiff = {
|
|
602
|
+
type: "list";
|
|
603
|
+
diff: Delta<(Value | Container)[]>[];
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
export type TextDiff = {
|
|
607
|
+
type: "text";
|
|
608
|
+
diff: Delta<string>[];
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
export type MapDiff = {
|
|
612
|
+
type: "map";
|
|
613
|
+
updated: Record<string, Value | Container | undefined>;
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
export type TreeDiffItem =
|
|
617
|
+
| {
|
|
618
|
+
target: TreeID;
|
|
619
|
+
action: "create";
|
|
620
|
+
parent: TreeID | undefined;
|
|
621
|
+
index: number;
|
|
622
|
+
fractionalIndex: string;
|
|
623
|
+
}
|
|
624
|
+
| {
|
|
625
|
+
target: TreeID;
|
|
626
|
+
action: "delete";
|
|
627
|
+
oldParent: TreeID | undefined;
|
|
628
|
+
oldIndex: number;
|
|
629
|
+
}
|
|
630
|
+
| {
|
|
631
|
+
target: TreeID;
|
|
632
|
+
action: "move";
|
|
633
|
+
parent: TreeID | undefined;
|
|
634
|
+
index: number;
|
|
635
|
+
fractionalIndex: string;
|
|
636
|
+
oldParent: TreeID | undefined;
|
|
637
|
+
oldIndex: number;
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
export type TreeDiff = {
|
|
641
|
+
type: "tree";
|
|
642
|
+
diff: TreeDiffItem[];
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
export type CounterDiff = {
|
|
646
|
+
type: "counter";
|
|
647
|
+
increment: number;
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
export type Diff = ListDiff | TextDiff | MapDiff | TreeDiff | CounterDiff;
|
|
651
|
+
export type Subscription = () => void;
|
|
652
|
+
type NonNullableType<T> = Exclude<T, null | undefined>;
|
|
653
|
+
export type AwarenessListener = (
|
|
654
|
+
arg: { updated: PeerID[]; added: PeerID[]; removed: PeerID[] },
|
|
655
|
+
origin: "local" | "timeout" | "remote" | string,
|
|
656
|
+
) => void;
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
interface Listener {
|
|
660
|
+
(event: LoroEventBatch): void;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
interface LoroDoc {
|
|
664
|
+
subscribe(listener: Listener): Subscription;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
interface UndoManager {
|
|
668
|
+
/**
|
|
669
|
+
* Set the callback function that is called when an undo/redo step is pushed.
|
|
670
|
+
* The function can return a meta data value that will be attached to the given stack item.
|
|
671
|
+
*
|
|
672
|
+
* @param listener - The callback function.
|
|
673
|
+
*/
|
|
674
|
+
setOnPush(listener?: UndoConfig["onPush"]): void;
|
|
675
|
+
/**
|
|
676
|
+
* Set the callback function that is called when an undo/redo step is popped.
|
|
677
|
+
* The function will have a meta data value that was attached to the given stack item when `onPush` was called.
|
|
678
|
+
*
|
|
679
|
+
* @param listener - The callback function.
|
|
680
|
+
*/
|
|
681
|
+
setOnPop(listener?: UndoConfig["onPop"]): void;
|
|
682
|
+
}
|
|
683
|
+
interface LoroDoc<T extends Record<string, Container> = Record<string, Container>> {
|
|
684
|
+
/**
|
|
685
|
+
* Get a LoroMap by container id
|
|
686
|
+
*
|
|
687
|
+
* The object returned is a new js object each time because it need to cross
|
|
688
|
+
* the WASM boundary.
|
|
689
|
+
*
|
|
690
|
+
* @example
|
|
691
|
+
* ```ts
|
|
692
|
+
* import { LoroDoc } from "loro-crdt";
|
|
693
|
+
*
|
|
694
|
+
* const doc = new LoroDoc();
|
|
695
|
+
* const map = doc.getMap("map");
|
|
696
|
+
* ```
|
|
697
|
+
*/
|
|
698
|
+
getMap<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroMap ? T[Key] : LoroMap;
|
|
699
|
+
/**
|
|
700
|
+
* Get a LoroList by container id
|
|
701
|
+
*
|
|
702
|
+
* The object returned is a new js object each time because it need to cross
|
|
703
|
+
* the WASM boundary.
|
|
704
|
+
*
|
|
705
|
+
* @example
|
|
706
|
+
* ```ts
|
|
707
|
+
* import { LoroDoc } from "loro-crdt";
|
|
708
|
+
*
|
|
709
|
+
* const doc = new LoroDoc();
|
|
710
|
+
* const list = doc.getList("list");
|
|
711
|
+
* ```
|
|
712
|
+
*/
|
|
713
|
+
getList<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroList ? T[Key] : LoroList;
|
|
714
|
+
/**
|
|
715
|
+
* Get a LoroMovableList by container id
|
|
716
|
+
*
|
|
717
|
+
* The object returned is a new js object each time because it need to cross
|
|
718
|
+
* the WASM boundary.
|
|
719
|
+
*
|
|
720
|
+
* @example
|
|
721
|
+
* ```ts
|
|
722
|
+
* import { LoroDoc } from "loro-crdt";
|
|
723
|
+
*
|
|
724
|
+
* const doc = new LoroDoc();
|
|
725
|
+
* const list = doc.getList("list");
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
getMovableList<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroMovableList ? T[Key] : LoroMovableList;
|
|
729
|
+
/**
|
|
730
|
+
* Get a LoroTree by container id
|
|
731
|
+
*
|
|
732
|
+
* The object returned is a new js object each time because it need to cross
|
|
733
|
+
* the WASM boundary.
|
|
734
|
+
*
|
|
735
|
+
* @example
|
|
736
|
+
* ```ts
|
|
737
|
+
* import { LoroDoc } from "loro-crdt";
|
|
738
|
+
*
|
|
739
|
+
* const doc = new LoroDoc();
|
|
740
|
+
* const tree = doc.getTree("tree");
|
|
741
|
+
* ```
|
|
742
|
+
*/
|
|
743
|
+
getTree<Key extends keyof T | ContainerID>(name: Key): T[Key] extends LoroTree ? T[Key] : LoroTree;
|
|
744
|
+
getText(key: string | ContainerID): LoroText;
|
|
745
|
+
}
|
|
746
|
+
interface LoroList<T = unknown> {
|
|
747
|
+
new(): LoroList<T>;
|
|
748
|
+
/**
|
|
749
|
+
* Get elements of the list. If the value is a child container, the corresponding
|
|
750
|
+
* `Container` will be returned.
|
|
751
|
+
*
|
|
752
|
+
* @example
|
|
753
|
+
* ```ts
|
|
754
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
755
|
+
*
|
|
756
|
+
* const doc = new LoroDoc();
|
|
757
|
+
* const list = doc.getList("list");
|
|
758
|
+
* list.insert(0, 100);
|
|
759
|
+
* list.insert(1, "foo");
|
|
760
|
+
* list.insert(2, true);
|
|
761
|
+
* list.insertContainer(3, new LoroText());
|
|
762
|
+
* console.log(list.value); // [100, "foo", true, LoroText];
|
|
763
|
+
* ```
|
|
764
|
+
*/
|
|
765
|
+
toArray(): T[];
|
|
766
|
+
/**
|
|
767
|
+
* Insert a container at the index.
|
|
768
|
+
*
|
|
769
|
+
* @example
|
|
770
|
+
* ```ts
|
|
771
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
772
|
+
*
|
|
773
|
+
* const doc = new LoroDoc();
|
|
774
|
+
* const list = doc.getList("list");
|
|
775
|
+
* list.insert(0, 100);
|
|
776
|
+
* const text = list.insertContainer(1, new LoroText());
|
|
777
|
+
* text.insert(0, "Hello");
|
|
778
|
+
* console.log(list.toJSON()); // [100, "Hello"];
|
|
779
|
+
* ```
|
|
780
|
+
*/
|
|
781
|
+
insertContainer<C extends Container>(pos: number, child: C): T extends C ? T : C;
|
|
782
|
+
/**
|
|
783
|
+
* Get the value at the index. If the value is a container, the corresponding handler will be returned.
|
|
784
|
+
*
|
|
785
|
+
* @example
|
|
786
|
+
* ```ts
|
|
787
|
+
* import { LoroDoc } from "loro-crdt";
|
|
788
|
+
*
|
|
789
|
+
* const doc = new LoroDoc();
|
|
790
|
+
* const list = doc.getList("list");
|
|
791
|
+
* list.insert(0, 100);
|
|
792
|
+
* console.log(list.get(0)); // 100
|
|
793
|
+
* console.log(list.get(1)); // undefined
|
|
794
|
+
* ```
|
|
795
|
+
*/
|
|
796
|
+
get(index: number): T;
|
|
797
|
+
/**
|
|
798
|
+
* Insert a value at index.
|
|
799
|
+
*
|
|
800
|
+
* @example
|
|
801
|
+
* ```ts
|
|
802
|
+
* import { LoroDoc } from "loro-crdt";
|
|
803
|
+
*
|
|
804
|
+
* const doc = new LoroDoc();
|
|
805
|
+
* const list = doc.getList("list");
|
|
806
|
+
* list.insert(0, 100);
|
|
807
|
+
* list.insert(1, "foo");
|
|
808
|
+
* list.insert(2, true);
|
|
809
|
+
* console.log(list.value); // [100, "foo", true];
|
|
810
|
+
* ```
|
|
811
|
+
*/
|
|
812
|
+
insert<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
|
813
|
+
delete(pos: number, len: number): void;
|
|
814
|
+
push<V extends T>(value: Exclude<V, Container>): void;
|
|
815
|
+
subscribe(listener: Listener): Subscription;
|
|
816
|
+
getAttached(): undefined | LoroList<T>;
|
|
817
|
+
}
|
|
818
|
+
interface LoroMovableList<T = unknown> {
|
|
819
|
+
new(): LoroMovableList<T>;
|
|
820
|
+
/**
|
|
821
|
+
* Get elements of the list. If the value is a child container, the corresponding
|
|
822
|
+
* `Container` will be returned.
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* ```ts
|
|
826
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
827
|
+
*
|
|
828
|
+
* const doc = new LoroDoc();
|
|
829
|
+
* const list = doc.getMovableList("list");
|
|
830
|
+
* list.insert(0, 100);
|
|
831
|
+
* list.insert(1, "foo");
|
|
832
|
+
* list.insert(2, true);
|
|
833
|
+
* list.insertContainer(3, new LoroText());
|
|
834
|
+
* console.log(list.value); // [100, "foo", true, LoroText];
|
|
835
|
+
* ```
|
|
836
|
+
*/
|
|
837
|
+
toArray(): T[];
|
|
838
|
+
/**
|
|
839
|
+
* Insert a container at the index.
|
|
840
|
+
*
|
|
841
|
+
* @example
|
|
842
|
+
* ```ts
|
|
843
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
844
|
+
*
|
|
845
|
+
* const doc = new LoroDoc();
|
|
846
|
+
* const list = doc.getMovableList("list");
|
|
847
|
+
* list.insert(0, 100);
|
|
848
|
+
* const text = list.insertContainer(1, new LoroText());
|
|
849
|
+
* text.insert(0, "Hello");
|
|
850
|
+
* console.log(list.toJSON()); // [100, "Hello"];
|
|
851
|
+
* ```
|
|
852
|
+
*/
|
|
853
|
+
insertContainer<C extends Container>(pos: number, child: C): T extends C ? T : C;
|
|
854
|
+
/**
|
|
855
|
+
* Get the value at the index. If the value is a container, the corresponding handler will be returned.
|
|
856
|
+
*
|
|
857
|
+
* @example
|
|
858
|
+
* ```ts
|
|
859
|
+
* import { LoroDoc } from "loro-crdt";
|
|
860
|
+
*
|
|
861
|
+
* const doc = new LoroDoc();
|
|
862
|
+
* const list = doc.getMovableList("list");
|
|
863
|
+
* list.insert(0, 100);
|
|
864
|
+
* console.log(list.get(0)); // 100
|
|
865
|
+
* console.log(list.get(1)); // undefined
|
|
866
|
+
* ```
|
|
867
|
+
*/
|
|
868
|
+
get(index: number): T;
|
|
869
|
+
/**
|
|
870
|
+
* Insert a value at index.
|
|
871
|
+
*
|
|
872
|
+
* @example
|
|
873
|
+
* ```ts
|
|
874
|
+
* import { LoroDoc } from "loro-crdt";
|
|
875
|
+
*
|
|
876
|
+
* const doc = new LoroDoc();
|
|
877
|
+
* const list = doc.getMovableList("list");
|
|
878
|
+
* list.insert(0, 100);
|
|
879
|
+
* list.insert(1, "foo");
|
|
880
|
+
* list.insert(2, true);
|
|
881
|
+
* console.log(list.value); // [100, "foo", true];
|
|
882
|
+
* ```
|
|
883
|
+
*/
|
|
884
|
+
insert<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
|
885
|
+
delete(pos: number, len: number): void;
|
|
886
|
+
push<V extends T>(value: Exclude<V, Container>): void;
|
|
887
|
+
subscribe(listener: Listener): Subscription;
|
|
888
|
+
getAttached(): undefined | LoroMovableList<T>;
|
|
889
|
+
/**
|
|
890
|
+
* Set the value at the given position.
|
|
891
|
+
*
|
|
892
|
+
* It's different from `delete` + `insert` that it will replace the value at the position.
|
|
893
|
+
*
|
|
894
|
+
* For example, if you have a list `[1, 2, 3]`, and you call `set(1, 100)`, the list will be `[1, 100, 3]`.
|
|
895
|
+
* If concurrently someone call `set(1, 200)`, the list will be `[1, 200, 3]` or `[1, 100, 3]`.
|
|
896
|
+
*
|
|
897
|
+
* But if you use `delete` + `insert` to simulate the set operation, they may create redundant operations
|
|
898
|
+
* and the final result will be `[1, 100, 200, 3]` or `[1, 200, 100, 3]`.
|
|
899
|
+
*
|
|
900
|
+
* @example
|
|
901
|
+
* ```ts
|
|
902
|
+
* import { LoroDoc } from "loro-crdt";
|
|
903
|
+
*
|
|
904
|
+
* const doc = new LoroDoc();
|
|
905
|
+
* const list = doc.getMovableList("list");
|
|
906
|
+
* list.insert(0, 100);
|
|
907
|
+
* list.insert(1, "foo");
|
|
908
|
+
* list.insert(2, true);
|
|
909
|
+
* list.set(1, "bar");
|
|
910
|
+
* console.log(list.value); // [100, "bar", true];
|
|
911
|
+
* ```
|
|
912
|
+
*/
|
|
913
|
+
set<V extends T>(pos: number, value: Exclude<V, Container>): void;
|
|
914
|
+
/**
|
|
915
|
+
* Set a container at the index.
|
|
916
|
+
*
|
|
917
|
+
* @example
|
|
918
|
+
* ```ts
|
|
919
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
920
|
+
*
|
|
921
|
+
* const doc = new LoroDoc();
|
|
922
|
+
* const list = doc.getMovableList("list");
|
|
923
|
+
* list.insert(0, 100);
|
|
924
|
+
* const text = list.setContainer(0, new LoroText());
|
|
925
|
+
* text.insert(0, "Hello");
|
|
926
|
+
* console.log(list.toJSON()); // ["Hello"];
|
|
927
|
+
* ```
|
|
928
|
+
*/
|
|
929
|
+
setContainer<C extends Container>(pos: number, child: C): T extends C ? T : C;
|
|
930
|
+
}
|
|
931
|
+
interface LoroMap<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
932
|
+
new(): LoroMap<T>;
|
|
933
|
+
/**
|
|
934
|
+
* Get the value of the key. If the value is a child container, the corresponding
|
|
935
|
+
* `Container` will be returned.
|
|
936
|
+
*
|
|
937
|
+
* The object returned is a new js object each time because it need to cross
|
|
938
|
+
*
|
|
939
|
+
* @example
|
|
940
|
+
* ```ts
|
|
941
|
+
* import { LoroDoc } from "loro-crdt";
|
|
942
|
+
*
|
|
943
|
+
* const doc = new LoroDoc();
|
|
944
|
+
* const map = doc.getMap("map");
|
|
945
|
+
* map.set("foo", "bar");
|
|
946
|
+
* const bar = map.get("foo");
|
|
947
|
+
* ```
|
|
948
|
+
*/
|
|
949
|
+
getOrCreateContainer<C extends Container>(key: string, child: C): C;
|
|
950
|
+
/**
|
|
951
|
+
* Set the key with a container.
|
|
952
|
+
*
|
|
953
|
+
* @example
|
|
954
|
+
* ```ts
|
|
955
|
+
* import { LoroDoc, LoroText, LoroList } from "loro-crdt";
|
|
956
|
+
*
|
|
957
|
+
* const doc = new LoroDoc();
|
|
958
|
+
* const map = doc.getMap("map");
|
|
959
|
+
* map.set("foo", "bar");
|
|
960
|
+
* const text = map.setContainer("text", new LoroText());
|
|
961
|
+
* const list = map.setContainer("list", new LoroList());
|
|
962
|
+
* ```
|
|
963
|
+
*/
|
|
964
|
+
setContainer<C extends Container, Key extends keyof T>(key: Key, child: C): NonNullableType<T[Key]> extends C ? NonNullableType<T[Key]> : C;
|
|
965
|
+
/**
|
|
966
|
+
* Get the value of the key. If the value is a child container, the corresponding
|
|
967
|
+
* `Container` will be returned.
|
|
968
|
+
*
|
|
969
|
+
* The object/value returned is a new js object/value each time because it need to cross
|
|
970
|
+
* the WASM boundary.
|
|
971
|
+
*
|
|
972
|
+
* @example
|
|
973
|
+
* ```ts
|
|
974
|
+
* import { LoroDoc } from "loro-crdt";
|
|
975
|
+
*
|
|
976
|
+
* const doc = new LoroDoc();
|
|
977
|
+
* const map = doc.getMap("map");
|
|
978
|
+
* map.set("foo", "bar");
|
|
979
|
+
* const bar = map.get("foo");
|
|
980
|
+
* ```
|
|
981
|
+
*/
|
|
982
|
+
get<Key extends keyof T>(key: Key): T[Key];
|
|
983
|
+
/**
|
|
984
|
+
* Set the key with the value.
|
|
985
|
+
*
|
|
986
|
+
* If the value of the key is exist, the old value will be updated.
|
|
987
|
+
*
|
|
988
|
+
* @example
|
|
989
|
+
* ```ts
|
|
990
|
+
* import { LoroDoc } from "loro-crdt";
|
|
991
|
+
*
|
|
992
|
+
* const doc = new LoroDoc();
|
|
993
|
+
* const map = doc.getMap("map");
|
|
994
|
+
* map.set("foo", "bar");
|
|
995
|
+
* map.set("foo", "baz");
|
|
996
|
+
* ```
|
|
997
|
+
*/
|
|
998
|
+
set<Key extends keyof T, V extends T[Key]>(key: Key, value: Exclude<V, Container>): void;
|
|
999
|
+
delete(key: string): void;
|
|
1000
|
+
subscribe(listener: Listener): Subscription;
|
|
1001
|
+
}
|
|
1002
|
+
interface LoroText {
|
|
1003
|
+
new(): LoroText;
|
|
1004
|
+
insert(pos: number, text: string): void;
|
|
1005
|
+
delete(pos: number, len: number): void;
|
|
1006
|
+
subscribe(listener: Listener): Subscription;
|
|
1007
|
+
}
|
|
1008
|
+
interface LoroTree<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
1009
|
+
new(): LoroTree<T>;
|
|
1010
|
+
/**
|
|
1011
|
+
* Create a new tree node as the child of parent and return a `LoroTreeNode` instance.
|
|
1012
|
+
* If the parent is undefined, the tree node will be a root node.
|
|
1013
|
+
*
|
|
1014
|
+
* If the index is not provided, the new node will be appended to the end.
|
|
1015
|
+
*
|
|
1016
|
+
* @example
|
|
1017
|
+
* ```ts
|
|
1018
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1019
|
+
*
|
|
1020
|
+
* const doc = new LoroDoc();
|
|
1021
|
+
* const tree = doc.getTree("tree");
|
|
1022
|
+
* const root = tree.createNode();
|
|
1023
|
+
* const node = tree.createNode(undefined, 0);
|
|
1024
|
+
*
|
|
1025
|
+
* // undefined
|
|
1026
|
+
* // / \
|
|
1027
|
+
* // node root
|
|
1028
|
+
* ```
|
|
1029
|
+
*/
|
|
1030
|
+
createNode(parent?: TreeID, index?: number): LoroTreeNode<T>;
|
|
1031
|
+
move(target: TreeID, parent?: TreeID, index?: number): void;
|
|
1032
|
+
delete(target: TreeID): void;
|
|
1033
|
+
has(target: TreeID): boolean;
|
|
1034
|
+
/**
|
|
1035
|
+
* Get LoroTreeNode by the TreeID.
|
|
1036
|
+
*/
|
|
1037
|
+
getNodeByID(target: TreeID): LoroTreeNode<T>;
|
|
1038
|
+
subscribe(listener: Listener): Subscription;
|
|
1039
|
+
}
|
|
1040
|
+
interface LoroTreeNode<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
1041
|
+
/**
|
|
1042
|
+
* Get the associated metadata map container of a tree node.
|
|
1043
|
+
*/
|
|
1044
|
+
readonly data: LoroMap<T>;
|
|
1045
|
+
/**
|
|
1046
|
+
* Create a new node as the child of the current node and
|
|
1047
|
+
* return an instance of `LoroTreeNode`.
|
|
1048
|
+
*
|
|
1049
|
+
* If the index is not provided, the new node will be appended to the end.
|
|
1050
|
+
*
|
|
1051
|
+
* @example
|
|
1052
|
+
* ```typescript
|
|
1053
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1054
|
+
*
|
|
1055
|
+
* let doc = new LoroDoc();
|
|
1056
|
+
* let tree = doc.getTree("tree");
|
|
1057
|
+
* let root = tree.createNode();
|
|
1058
|
+
* let node = root.createNode();
|
|
1059
|
+
* let node2 = root.createNode(0);
|
|
1060
|
+
* // root
|
|
1061
|
+
* // / \
|
|
1062
|
+
* // node2 node
|
|
1063
|
+
* ```
|
|
1064
|
+
*/
|
|
1065
|
+
createNode(index?: number): LoroTreeNode<T>;
|
|
1066
|
+
move(parent?: LoroTreeNode<T>, index?: number): void;
|
|
1067
|
+
parent(): LoroTreeNode<T> | undefined;
|
|
1068
|
+
/**
|
|
1069
|
+
* Get the children of this node.
|
|
1070
|
+
*
|
|
1071
|
+
* The objects returned are new js objects each time because they need to cross
|
|
1072
|
+
* the WASM boundary.
|
|
1073
|
+
*/
|
|
1074
|
+
children(): Array<LoroTreeNode<T>> | undefined;
|
|
1075
|
+
}
|
|
1076
|
+
interface AwarenessWasm<T extends Value = Value> {
|
|
1077
|
+
getState(peer: PeerID): T | undefined;
|
|
1078
|
+
getTimestamp(peer: PeerID): number | undefined;
|
|
1079
|
+
getAllStates(): Record<PeerID, T>;
|
|
1080
|
+
setLocalState(value: T): void;
|
|
1081
|
+
removeOutdated(): PeerID[];
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
/**
|
|
1087
|
+
* `Awareness` is a structure that tracks the ephemeral state of peers.
|
|
1088
|
+
*
|
|
1089
|
+
* It can be used to synchronize cursor positions, selections, and the names of the peers.
|
|
1090
|
+
*
|
|
1091
|
+
* The state of a specific peer is expected to be removed after a specified timeout. Use
|
|
1092
|
+
* `remove_outdated` to eliminate outdated states.
|
|
1093
|
+
*/
|
|
1094
|
+
export class AwarenessWasm {
|
|
1095
|
+
free(): void;
|
|
1096
|
+
/**
|
|
1097
|
+
* Creates a new `Awareness` instance.
|
|
1098
|
+
*
|
|
1099
|
+
* The `timeout` parameter specifies the duration in milliseconds.
|
|
1100
|
+
* A state of a peer is considered outdated, if the last update of the state of the peer
|
|
1101
|
+
* is older than the `timeout`.
|
|
1102
|
+
* @param {number | bigint | `${number}`} peer
|
|
1103
|
+
* @param {number} timeout
|
|
1104
|
+
*/
|
|
1105
|
+
constructor(peer: number | bigint | `${number}`, timeout: number);
|
|
1106
|
+
/**
|
|
1107
|
+
* Encodes the state of the given peers.
|
|
1108
|
+
* @param {Array<any>} peers
|
|
1109
|
+
* @returns {Uint8Array}
|
|
1110
|
+
*/
|
|
1111
|
+
encode(peers: Array<any>): Uint8Array;
|
|
1112
|
+
/**
|
|
1113
|
+
* Encodes the state of all peers.
|
|
1114
|
+
* @returns {Uint8Array}
|
|
1115
|
+
*/
|
|
1116
|
+
encodeAll(): Uint8Array;
|
|
1117
|
+
/**
|
|
1118
|
+
* Applies the encoded state of peers.
|
|
1119
|
+
*
|
|
1120
|
+
* Each peer's deletion countdown will be reset upon update, requiring them to pass through the `timeout`
|
|
1121
|
+
* interval again before being eligible for deletion.
|
|
1122
|
+
* @param {Uint8Array} encoded_peers_info
|
|
1123
|
+
* @returns {{ updated: PeerID[], added: PeerID[] }}
|
|
1124
|
+
*/
|
|
1125
|
+
apply(encoded_peers_info: Uint8Array): { updated: PeerID[], added: PeerID[] };
|
|
1126
|
+
/**
|
|
1127
|
+
* Get the PeerID of the local peer.
|
|
1128
|
+
* @returns {PeerID}
|
|
1129
|
+
*/
|
|
1130
|
+
peer(): PeerID;
|
|
1131
|
+
/**
|
|
1132
|
+
* Get the timestamp of the state of a given peer.
|
|
1133
|
+
* @param {number | bigint | `${number}`} peer
|
|
1134
|
+
* @returns {number | undefined}
|
|
1135
|
+
*/
|
|
1136
|
+
getTimestamp(peer: number | bigint | `${number}`): number | undefined;
|
|
1137
|
+
/**
|
|
1138
|
+
* Remove the states of outdated peers.
|
|
1139
|
+
* @returns {(PeerID)[]}
|
|
1140
|
+
*/
|
|
1141
|
+
removeOutdated(): (PeerID)[];
|
|
1142
|
+
/**
|
|
1143
|
+
* Get the number of peers.
|
|
1144
|
+
* @returns {number}
|
|
1145
|
+
*/
|
|
1146
|
+
length(): number;
|
|
1147
|
+
/**
|
|
1148
|
+
* If the state is empty.
|
|
1149
|
+
* @returns {boolean}
|
|
1150
|
+
*/
|
|
1151
|
+
isEmpty(): boolean;
|
|
1152
|
+
/**
|
|
1153
|
+
* Get all the peers
|
|
1154
|
+
* @returns {(PeerID)[]}
|
|
1155
|
+
*/
|
|
1156
|
+
peers(): (PeerID)[];
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Cursor is a stable position representation in the doc.
|
|
1160
|
+
* When expressing the position of a cursor, using "index" can be unstable
|
|
1161
|
+
* because the cursor's position may change due to other deletions and insertions,
|
|
1162
|
+
* requiring updates with each edit. To stably represent a position or range within
|
|
1163
|
+
* a list structure, we can utilize the ID of each item/character on List CRDT or
|
|
1164
|
+
* Text CRDT for expression.
|
|
1165
|
+
*
|
|
1166
|
+
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
|
|
1167
|
+
* approach complicates tracking cursors since they rely on these IDs. The solution
|
|
1168
|
+
* recalculates position by replaying relevant history to update cursors
|
|
1169
|
+
* accurately. To minimize the performance impact of history replay, the system
|
|
1170
|
+
* updates cursor info to reference only the IDs of currently present elements,
|
|
1171
|
+
* thereby reducing the need for replay.
|
|
1172
|
+
*
|
|
1173
|
+
* @example
|
|
1174
|
+
* ```ts
|
|
1175
|
+
*
|
|
1176
|
+
* const doc = new LoroDoc();
|
|
1177
|
+
* const text = doc.getText("text");
|
|
1178
|
+
* text.insert(0, "123");
|
|
1179
|
+
* const pos0 = text.getCursor(0, 0);
|
|
1180
|
+
* {
|
|
1181
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
1182
|
+
* expect(ans.offset).toBe(0);
|
|
1183
|
+
* }
|
|
1184
|
+
* text.insert(0, "1");
|
|
1185
|
+
* {
|
|
1186
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
1187
|
+
* expect(ans.offset).toBe(1);
|
|
1188
|
+
* }
|
|
1189
|
+
* ```
|
|
1190
|
+
*/
|
|
1191
|
+
export class Cursor {
|
|
1192
|
+
free(): void;
|
|
1193
|
+
/**
|
|
1194
|
+
* Get the id of the given container.
|
|
1195
|
+
* @returns {ContainerID}
|
|
1196
|
+
*/
|
|
1197
|
+
containerId(): ContainerID;
|
|
1198
|
+
/**
|
|
1199
|
+
* Get the ID that represents the position.
|
|
1200
|
+
*
|
|
1201
|
+
* It can be undefined if it's not bind into a specific ID.
|
|
1202
|
+
* @returns {{ peer: PeerID, counter: number } | undefined}
|
|
1203
|
+
*/
|
|
1204
|
+
pos(): { peer: PeerID, counter: number } | undefined;
|
|
1205
|
+
/**
|
|
1206
|
+
* Get which side of the character/list item the cursor is on.
|
|
1207
|
+
* @returns {Side}
|
|
1208
|
+
*/
|
|
1209
|
+
side(): Side;
|
|
1210
|
+
/**
|
|
1211
|
+
* Encode the cursor into a Uint8Array.
|
|
1212
|
+
* @returns {Uint8Array}
|
|
1213
|
+
*/
|
|
1214
|
+
encode(): Uint8Array;
|
|
1215
|
+
/**
|
|
1216
|
+
* Decode the cursor from a Uint8Array.
|
|
1217
|
+
* @param {Uint8Array} data
|
|
1218
|
+
* @returns {Cursor}
|
|
1219
|
+
*/
|
|
1220
|
+
static decode(data: Uint8Array): Cursor;
|
|
1221
|
+
/**
|
|
1222
|
+
* "Cursor"
|
|
1223
|
+
* @returns {any}
|
|
1224
|
+
*/
|
|
1225
|
+
kind(): any;
|
|
1226
|
+
}
|
|
1227
|
+
/**
|
|
1228
|
+
* The handler of a tree(forest) container.
|
|
1229
|
+
*/
|
|
1230
|
+
export class LoroCounter {
|
|
1231
|
+
free(): void;
|
|
1232
|
+
/**
|
|
1233
|
+
* Create a new LoroCounter.
|
|
1234
|
+
*/
|
|
1235
|
+
constructor();
|
|
1236
|
+
/**
|
|
1237
|
+
* Increment the counter by the given value.
|
|
1238
|
+
* @param {number} value
|
|
1239
|
+
*/
|
|
1240
|
+
increment(value: number): void;
|
|
1241
|
+
/**
|
|
1242
|
+
* Decrement the counter by the given value.
|
|
1243
|
+
* @param {number} value
|
|
1244
|
+
*/
|
|
1245
|
+
decrement(value: number): void;
|
|
1246
|
+
/**
|
|
1247
|
+
* Subscribe to the changes of the counter.
|
|
1248
|
+
* @param {Function} f
|
|
1249
|
+
* @returns {any}
|
|
1250
|
+
*/
|
|
1251
|
+
subscribe(f: Function): any;
|
|
1252
|
+
/**
|
|
1253
|
+
* Get the parent container of the counter container.
|
|
1254
|
+
*
|
|
1255
|
+
* - The parent container of the root counter is `undefined`.
|
|
1256
|
+
* - The object returned is a new js object each time because it need to cross
|
|
1257
|
+
* the WASM boundary.
|
|
1258
|
+
* @returns {Container | undefined}
|
|
1259
|
+
*/
|
|
1260
|
+
parent(): Container | undefined;
|
|
1261
|
+
/**
|
|
1262
|
+
* Whether the container is attached to a docuemnt.
|
|
1263
|
+
*
|
|
1264
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
1265
|
+
* @returns {boolean}
|
|
1266
|
+
*/
|
|
1267
|
+
isAttached(): boolean;
|
|
1268
|
+
/**
|
|
1269
|
+
* Get the attached container associated with this.
|
|
1270
|
+
*
|
|
1271
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
1272
|
+
* @returns {LoroTree | undefined}
|
|
1273
|
+
*/
|
|
1274
|
+
getAttached(): LoroTree | undefined;
|
|
1275
|
+
/**
|
|
1276
|
+
* Get the value of the counter.
|
|
1277
|
+
*/
|
|
1278
|
+
readonly value: number;
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* The CRDTs document. Loro supports different CRDTs include [**List**](LoroList),
|
|
1282
|
+
* [**RichText**](LoroText), [**Map**](LoroMap) and [**Movable Tree**](LoroTree),
|
|
1283
|
+
* you could build all kind of applications by these.
|
|
1284
|
+
*
|
|
1285
|
+
* @example
|
|
1286
|
+
* ```ts
|
|
1287
|
+
* import { LoroDoc } from "loro-crdt"
|
|
1288
|
+
*
|
|
1289
|
+
* const loro = new LoroDoc();
|
|
1290
|
+
* const text = loro.getText("text");
|
|
1291
|
+
* const list = loro.getList("list");
|
|
1292
|
+
* const map = loro.getMap("Map");
|
|
1293
|
+
* const tree = loro.getTree("tree");
|
|
1294
|
+
* ```
|
|
1295
|
+
*/
|
|
1296
|
+
export class LoroDoc {
|
|
1297
|
+
free(): void;
|
|
1298
|
+
/**
|
|
1299
|
+
* Create a new loro document.
|
|
1300
|
+
*
|
|
1301
|
+
* New document will have a random peer id.
|
|
1302
|
+
*/
|
|
1303
|
+
constructor();
|
|
1304
|
+
/**
|
|
1305
|
+
* Enables editing in detached mode, which is disabled by default.
|
|
1306
|
+
*
|
|
1307
|
+
* The doc enter detached mode after calling `detach` or checking out a non-latest version.
|
|
1308
|
+
*
|
|
1309
|
+
* # Important Notes:
|
|
1310
|
+
*
|
|
1311
|
+
* - This mode uses a different PeerID for each checkout.
|
|
1312
|
+
* - Ensure no concurrent operations share the same PeerID if set manually.
|
|
1313
|
+
* - Importing does not affect the document's state or version; changes are
|
|
1314
|
+
* recorded in the [OpLog] only. Call `checkout` to apply changes.
|
|
1315
|
+
* @param {boolean} enable
|
|
1316
|
+
*/
|
|
1317
|
+
setDetachedEditing(enable: boolean): void;
|
|
1318
|
+
/**
|
|
1319
|
+
* Whether the editing is enabled in detached mode.
|
|
1320
|
+
*
|
|
1321
|
+
* The doc enter detached mode after calling `detach` or checking out a non-latest version.
|
|
1322
|
+
*
|
|
1323
|
+
* # Important Notes:
|
|
1324
|
+
*
|
|
1325
|
+
* - This mode uses a different PeerID for each checkout.
|
|
1326
|
+
* - Ensure no concurrent operations share the same PeerID if set manually.
|
|
1327
|
+
* - Importing does not affect the document's state or version; changes are
|
|
1328
|
+
* recorded in the [OpLog] only. Call `checkout` to apply changes.
|
|
1329
|
+
* @returns {boolean}
|
|
1330
|
+
*/
|
|
1331
|
+
isDetachedEditingEnabled(): boolean;
|
|
1332
|
+
/**
|
|
1333
|
+
* Set whether to record the timestamp of each change. Default is `false`.
|
|
1334
|
+
*
|
|
1335
|
+
* If enabled, the Unix timestamp (in seconds) will be recorded for each change automatically.
|
|
1336
|
+
*
|
|
1337
|
+
* You can also set each timestamp manually when you commit a change.
|
|
1338
|
+
* The timestamp manually set will override the automatic one.
|
|
1339
|
+
*
|
|
1340
|
+
* NOTE: Timestamps are forced to be in ascending order in the OpLog's history.
|
|
1341
|
+
* If you commit a new change with a timestamp that is less than the existing one,
|
|
1342
|
+
* the largest existing timestamp will be used instead.
|
|
1343
|
+
* @param {boolean} auto_record
|
|
1344
|
+
*/
|
|
1345
|
+
setRecordTimestamp(auto_record: boolean): void;
|
|
1346
|
+
/**
|
|
1347
|
+
* If two continuous local changes are within the interval, they will be merged into one change.
|
|
1348
|
+
*
|
|
1349
|
+
* The default value is 1_000_000, the default unit is seconds.
|
|
1350
|
+
* @param {number} interval
|
|
1351
|
+
*/
|
|
1352
|
+
setChangeMergeInterval(interval: number): void;
|
|
1353
|
+
/**
|
|
1354
|
+
* Set the rich text format configuration of the document.
|
|
1355
|
+
*
|
|
1356
|
+
* You need to config it if you use rich text `mark` method.
|
|
1357
|
+
* Specifically, you need to config the `expand` property of each style.
|
|
1358
|
+
*
|
|
1359
|
+
* Expand is used to specify the behavior of expanding when new text is inserted at the
|
|
1360
|
+
* beginning or end of the style.
|
|
1361
|
+
*
|
|
1362
|
+
* You can specify the `expand` option to set the behavior when inserting text at the boundary of the range.
|
|
1363
|
+
*
|
|
1364
|
+
* - `after`(default): when inserting text right after the given range, the mark will be expanded to include the inserted text
|
|
1365
|
+
* - `before`: when inserting text right before the given range, the mark will be expanded to include the inserted text
|
|
1366
|
+
* - `none`: the mark will not be expanded to include the inserted text at the boundaries
|
|
1367
|
+
* - `both`: when inserting text either right before or right after the given range, the mark will be expanded to include the inserted text
|
|
1368
|
+
*
|
|
1369
|
+
* @example
|
|
1370
|
+
* ```ts
|
|
1371
|
+
* const doc = new LoroDoc();
|
|
1372
|
+
* doc.configTextStyle({
|
|
1373
|
+
* bold: { expand: "after" },
|
|
1374
|
+
* link: { expand: "before" }
|
|
1375
|
+
* });
|
|
1376
|
+
* const text = doc.getText("text");
|
|
1377
|
+
* text.insert(0, "Hello World!");
|
|
1378
|
+
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
1379
|
+
* expect(text.toDelta()).toStrictEqual([
|
|
1380
|
+
* {
|
|
1381
|
+
* insert: "Hello",
|
|
1382
|
+
* attributes: {
|
|
1383
|
+
* bold: true,
|
|
1384
|
+
* },
|
|
1385
|
+
* },
|
|
1386
|
+
* {
|
|
1387
|
+
* insert: " World!",
|
|
1388
|
+
* },
|
|
1389
|
+
* ] as Delta<string>[]);
|
|
1390
|
+
* ```
|
|
1391
|
+
* @param {{[key: string]: { expand: 'before'|'after'|'none'|'both' }}} styles
|
|
1392
|
+
*/
|
|
1393
|
+
configTextStyle(styles: {[key: string]: { expand: 'before'|'after'|'none'|'both' }}): void;
|
|
1394
|
+
/**
|
|
1395
|
+
* Create a loro document from the snapshot.
|
|
1396
|
+
*
|
|
1397
|
+
* @see You can learn more [here](https://loro.dev/docs/tutorial/encoding).
|
|
1398
|
+
*
|
|
1399
|
+
* @example
|
|
1400
|
+
* ```ts
|
|
1401
|
+
* import { LoroDoc } from "loro-crdt"
|
|
1402
|
+
*
|
|
1403
|
+
* const doc = new LoroDoc();
|
|
1404
|
+
* // ...
|
|
1405
|
+
* const bytes = doc.export({ mode: "snapshot" });
|
|
1406
|
+
* const loro = LoroDoc.fromSnapshot(bytes);
|
|
1407
|
+
* ```
|
|
1408
|
+
* @param {Uint8Array} snapshot
|
|
1409
|
+
* @returns {LoroDoc}
|
|
1410
|
+
*/
|
|
1411
|
+
static fromSnapshot(snapshot: Uint8Array): LoroDoc;
|
|
1412
|
+
/**
|
|
1413
|
+
* Attach the document state to the latest known version.
|
|
1414
|
+
*
|
|
1415
|
+
* > The document becomes detached during a `checkout` operation.
|
|
1416
|
+
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
1417
|
+
* > In a detached state, the document is not editable, and any `import` operations will be
|
|
1418
|
+
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
1419
|
+
*
|
|
1420
|
+
* This method has the same effect as invoking `checkoutToLatest`.
|
|
1421
|
+
*
|
|
1422
|
+
* @example
|
|
1423
|
+
* ```ts
|
|
1424
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1425
|
+
*
|
|
1426
|
+
* const doc = new LoroDoc();
|
|
1427
|
+
* const text = doc.getText("text");
|
|
1428
|
+
* const frontiers = doc.frontiers();
|
|
1429
|
+
* text.insert(0, "Hello World!");
|
|
1430
|
+
* doc.checkout(frontiers);
|
|
1431
|
+
* // you need call `attach()` or `checkoutToLatest()` before changing the doc.
|
|
1432
|
+
* doc.attach();
|
|
1433
|
+
* text.insert(0, "Hi");
|
|
1434
|
+
* ```
|
|
1435
|
+
*/
|
|
1436
|
+
attach(): void;
|
|
1437
|
+
/**
|
|
1438
|
+
* `detached` indicates that the `DocState` is not synchronized with the latest version of `OpLog`.
|
|
1439
|
+
*
|
|
1440
|
+
* > The document becomes detached during a `checkout` operation.
|
|
1441
|
+
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
1442
|
+
* > In a detached state, the document is not editable by default, and any `import` operations will be
|
|
1443
|
+
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
1444
|
+
*
|
|
1445
|
+
* @example
|
|
1446
|
+
* ```ts
|
|
1447
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1448
|
+
*
|
|
1449
|
+
* const doc = new LoroDoc();
|
|
1450
|
+
* const text = doc.getText("text");
|
|
1451
|
+
* const frontiers = doc.frontiers();
|
|
1452
|
+
* text.insert(0, "Hello World!");
|
|
1453
|
+
* console.log(doc.isDetached()); // false
|
|
1454
|
+
* doc.checkout(frontiers);
|
|
1455
|
+
* console.log(doc.isDetached()); // true
|
|
1456
|
+
* doc.attach();
|
|
1457
|
+
* console.log(doc.isDetached()); // false
|
|
1458
|
+
* ```
|
|
1459
|
+
* @returns {boolean}
|
|
1460
|
+
*/
|
|
1461
|
+
isDetached(): boolean;
|
|
1462
|
+
/**
|
|
1463
|
+
* Detach the document state from the latest known version.
|
|
1464
|
+
*
|
|
1465
|
+
* After detaching, all import operations will be recorded in the `OpLog` without being applied to the `DocState`.
|
|
1466
|
+
* When `detached`, the document is not editable.
|
|
1467
|
+
*
|
|
1468
|
+
* @example
|
|
1469
|
+
* ```ts
|
|
1470
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1471
|
+
*
|
|
1472
|
+
* const doc = new LoroDoc();
|
|
1473
|
+
* doc.detach();
|
|
1474
|
+
* console.log(doc.isDetached()); // true
|
|
1475
|
+
* ```
|
|
1476
|
+
*/
|
|
1477
|
+
detach(): void;
|
|
1478
|
+
/**
|
|
1479
|
+
* Duplicate the document with a different PeerID
|
|
1480
|
+
*
|
|
1481
|
+
* The time complexity and space complexity of this operation are both O(n),
|
|
1482
|
+
* @returns {LoroDoc}
|
|
1483
|
+
*/
|
|
1484
|
+
fork(): LoroDoc;
|
|
1485
|
+
/**
|
|
1486
|
+
* Creates a new LoroDoc at a specified version (Frontiers)
|
|
1487
|
+
* @param {({ peer: PeerID, counter: number })[]} frontiers
|
|
1488
|
+
* @returns {LoroDoc}
|
|
1489
|
+
*/
|
|
1490
|
+
forkAt(frontiers: ({ peer: PeerID, counter: number })[]): LoroDoc;
|
|
1491
|
+
/**
|
|
1492
|
+
* Checkout the `DocState` to the latest version of `OpLog`.
|
|
1493
|
+
*
|
|
1494
|
+
* > The document becomes detached during a `checkout` operation.
|
|
1495
|
+
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
1496
|
+
* > In a detached state, the document is not editable by default, and any `import` operations will be
|
|
1497
|
+
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
1498
|
+
*
|
|
1499
|
+
* This has the same effect as `attach`.
|
|
1500
|
+
*
|
|
1501
|
+
* @example
|
|
1502
|
+
* ```ts
|
|
1503
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1504
|
+
*
|
|
1505
|
+
* const doc = new LoroDoc();
|
|
1506
|
+
* const text = doc.getText("text");
|
|
1507
|
+
* const frontiers = doc.frontiers();
|
|
1508
|
+
* text.insert(0, "Hello World!");
|
|
1509
|
+
* doc.checkout(frontiers);
|
|
1510
|
+
* // you need call `checkoutToLatest()` or `attach()` before changing the doc.
|
|
1511
|
+
* doc.checkoutToLatest();
|
|
1512
|
+
* text.insert(0, "Hi");
|
|
1513
|
+
* ```
|
|
1514
|
+
*/
|
|
1515
|
+
checkoutToLatest(): void;
|
|
1516
|
+
/**
|
|
1517
|
+
* Visit all the ancestors of the changes in causal order.
|
|
1518
|
+
*
|
|
1519
|
+
* @param ids - the changes to visit
|
|
1520
|
+
* @param f - the callback function, return `true` to continue visiting, return `false` to stop
|
|
1521
|
+
* @param {({ peer: PeerID, counter: number })[]} ids
|
|
1522
|
+
* @param {Function} f
|
|
1523
|
+
*/
|
|
1524
|
+
travelChangeAncestors(ids: ({ peer: PeerID, counter: number })[], f: Function): void;
|
|
1525
|
+
/**
|
|
1526
|
+
* Checkout the `DocState` to a specific version.
|
|
1527
|
+
*
|
|
1528
|
+
* > The document becomes detached during a `checkout` operation.
|
|
1529
|
+
* > Being `detached` implies that the `DocState` is not synchronized with the latest version of the `OpLog`.
|
|
1530
|
+
* > In a detached state, the document is not editable, and any `import` operations will be
|
|
1531
|
+
* > recorded in the `OpLog` without being applied to the `DocState`.
|
|
1532
|
+
*
|
|
1533
|
+
* You should call `attach` to attach the `DocState` to the latest version of `OpLog`.
|
|
1534
|
+
*
|
|
1535
|
+
* @param frontiers - the specific frontiers
|
|
1536
|
+
*
|
|
1537
|
+
* @example
|
|
1538
|
+
* ```ts
|
|
1539
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1540
|
+
*
|
|
1541
|
+
* const doc = new LoroDoc();
|
|
1542
|
+
* const text = doc.getText("text");
|
|
1543
|
+
* const frontiers = doc.frontiers();
|
|
1544
|
+
* text.insert(0, "Hello World!");
|
|
1545
|
+
* doc.checkout(frontiers);
|
|
1546
|
+
* console.log(doc.toJSON()); // {"text": ""}
|
|
1547
|
+
* ```
|
|
1548
|
+
* @param {({ peer: PeerID, counter: number })[]} frontiers
|
|
1549
|
+
*/
|
|
1550
|
+
checkout(frontiers: ({ peer: PeerID, counter: number })[]): void;
|
|
1551
|
+
/**
|
|
1552
|
+
* Set the peer ID of the current writer.
|
|
1553
|
+
*
|
|
1554
|
+
* It must be a number, a BigInt, or a decimal string that can be parsed to a unsigned 64-bit integer.
|
|
1555
|
+
*
|
|
1556
|
+
* Note: use it with caution. You need to make sure there is not chance that two peers
|
|
1557
|
+
* have the same peer ID. Otherwise, we cannot ensure the consistency of the document.
|
|
1558
|
+
* @param {number | bigint | `${number}`} peer_id
|
|
1559
|
+
*/
|
|
1560
|
+
setPeerId(peer_id: number | bigint | `${number}`): void;
|
|
1561
|
+
/**
|
|
1562
|
+
* Commit the cumulative auto committed transaction.
|
|
1563
|
+
*
|
|
1564
|
+
* You can specify the `origin`, `timestamp`, and `message` of the commit.
|
|
1565
|
+
*
|
|
1566
|
+
* - The `origin` is used to mark the event
|
|
1567
|
+
* - The `message` works like a git commit message, which will be recorded and synced to peers
|
|
1568
|
+
*
|
|
1569
|
+
* The events will be emitted after a transaction is committed. A transaction is committed when:
|
|
1570
|
+
*
|
|
1571
|
+
* - `doc.commit()` is called.
|
|
1572
|
+
* - `doc.export(mode)` is called.
|
|
1573
|
+
* - `doc.import(data)` is called.
|
|
1574
|
+
* - `doc.checkout(version)` is called.
|
|
1575
|
+
*
|
|
1576
|
+
* NOTE: Timestamps are forced to be in ascending order.
|
|
1577
|
+
* If you commit a new change with a timestamp that is less than the existing one,
|
|
1578
|
+
* the largest existing timestamp will be used instead.
|
|
1579
|
+
*
|
|
1580
|
+
* NOTE: The `origin` will not be persisted, but the `message` will.
|
|
1581
|
+
* @param {{ origin?: string, timestamp?: number, message?: string } | undefined} [options]
|
|
1582
|
+
*/
|
|
1583
|
+
commit(options?: { origin?: string, timestamp?: number, message?: string }): void;
|
|
1584
|
+
/**
|
|
1585
|
+
* Get the number of operations in the pending transaction.
|
|
1586
|
+
*
|
|
1587
|
+
* The pending transaction is the one that is not committed yet. It will be committed
|
|
1588
|
+
* automatically after calling `doc.commit()`, `doc.export(mode)` or `doc.checkout(version)`.
|
|
1589
|
+
* @returns {number}
|
|
1590
|
+
*/
|
|
1591
|
+
getPendingTxnLength(): number;
|
|
1592
|
+
/**
|
|
1593
|
+
* Get a LoroText by container id.
|
|
1594
|
+
*
|
|
1595
|
+
* The object returned is a new js object each time because it need to cross
|
|
1596
|
+
* the WASM boundary.
|
|
1597
|
+
*
|
|
1598
|
+
* @example
|
|
1599
|
+
* ```ts
|
|
1600
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1601
|
+
*
|
|
1602
|
+
* const doc = new LoroDoc();
|
|
1603
|
+
* const text = doc.getText("text");
|
|
1604
|
+
* ```
|
|
1605
|
+
* @param {ContainerID | string} cid
|
|
1606
|
+
* @returns {LoroText}
|
|
1607
|
+
*/
|
|
1608
|
+
getText(cid: ContainerID | string): LoroText;
|
|
1609
|
+
/**
|
|
1610
|
+
* Get a LoroCounter by container id
|
|
1611
|
+
* @param {ContainerID | string} cid
|
|
1612
|
+
* @returns {LoroCounter}
|
|
1613
|
+
*/
|
|
1614
|
+
getCounter(cid: ContainerID | string): LoroCounter;
|
|
1615
|
+
/**
|
|
1616
|
+
* Set the commit message of the next commit
|
|
1617
|
+
* @param {string} msg
|
|
1618
|
+
*/
|
|
1619
|
+
setNextCommitMessage(msg: string): void;
|
|
1620
|
+
/**
|
|
1621
|
+
* Get deep value of the document with container id
|
|
1622
|
+
* @returns {any}
|
|
1623
|
+
*/
|
|
1624
|
+
getDeepValueWithID(): any;
|
|
1625
|
+
/**
|
|
1626
|
+
* Get the path from the root to the container
|
|
1627
|
+
* @param {ContainerID} id
|
|
1628
|
+
* @returns {Array<any> | undefined}
|
|
1629
|
+
*/
|
|
1630
|
+
getPathToContainer(id: ContainerID): Array<any> | undefined;
|
|
1631
|
+
/**
|
|
1632
|
+
* Evaluate JSONPath against a LoroDoc
|
|
1633
|
+
* @param {string} jsonpath
|
|
1634
|
+
* @returns {Array<any>}
|
|
1635
|
+
*/
|
|
1636
|
+
JSONPath(jsonpath: string): Array<any>;
|
|
1637
|
+
/**
|
|
1638
|
+
* Get the version vector of the current document state.
|
|
1639
|
+
*
|
|
1640
|
+
* If you checkout to a specific version, the version vector will change.
|
|
1641
|
+
* @returns {VersionVector}
|
|
1642
|
+
*/
|
|
1643
|
+
version(): VersionVector;
|
|
1644
|
+
/**
|
|
1645
|
+
* The doc only contains the history since this version
|
|
1646
|
+
*
|
|
1647
|
+
* This is empty if the doc is not shallow.
|
|
1648
|
+
*
|
|
1649
|
+
* The ops included by the shallow history start version vector are not in the doc.
|
|
1650
|
+
* @returns {VersionVector}
|
|
1651
|
+
*/
|
|
1652
|
+
shallowSinceVV(): VersionVector;
|
|
1653
|
+
/**
|
|
1654
|
+
* Check if the doc contains the full history.
|
|
1655
|
+
* @returns {boolean}
|
|
1656
|
+
*/
|
|
1657
|
+
isShallow(): boolean;
|
|
1658
|
+
/**
|
|
1659
|
+
* The doc only contains the history since this version
|
|
1660
|
+
*
|
|
1661
|
+
* This is empty if the doc is not shallow.
|
|
1662
|
+
*
|
|
1663
|
+
* The ops included by the shallow history start frontiers are not in the doc.
|
|
1664
|
+
* @returns {{ peer: PeerID, counter: number }[]}
|
|
1665
|
+
*/
|
|
1666
|
+
shallowSinceFrontiers(): { peer: PeerID, counter: number }[];
|
|
1667
|
+
/**
|
|
1668
|
+
* Get the version vector of the latest known version in OpLog.
|
|
1669
|
+
*
|
|
1670
|
+
* If you checkout to a specific version, this version vector will not change.
|
|
1671
|
+
* @returns {VersionVector}
|
|
1672
|
+
*/
|
|
1673
|
+
oplogVersion(): VersionVector;
|
|
1674
|
+
/**
|
|
1675
|
+
* Get the [frontiers](https://loro.dev/docs/advanced/version_deep_dive) of the current document state.
|
|
1676
|
+
*
|
|
1677
|
+
* If you checkout to a specific version, this value will change.
|
|
1678
|
+
* @returns {{ peer: PeerID, counter: number }[]}
|
|
1679
|
+
*/
|
|
1680
|
+
frontiers(): { peer: PeerID, counter: number }[];
|
|
1681
|
+
/**
|
|
1682
|
+
* Get the [frontiers](https://loro.dev/docs/advanced/version_deep_dive) of the latest version in OpLog.
|
|
1683
|
+
*
|
|
1684
|
+
* If you checkout to a specific version, this value will not change.
|
|
1685
|
+
* @returns {{ peer: PeerID, counter: number }[]}
|
|
1686
|
+
*/
|
|
1687
|
+
oplogFrontiers(): { peer: PeerID, counter: number }[];
|
|
1688
|
+
/**
|
|
1689
|
+
* Compare the version of the OpLog with the specified frontiers.
|
|
1690
|
+
*
|
|
1691
|
+
* This method is useful to compare the version by only a small amount of data.
|
|
1692
|
+
*
|
|
1693
|
+
* This method returns an integer indicating the relationship between the version of the OpLog (referred to as 'self')
|
|
1694
|
+
* and the provided 'frontiers' parameter:
|
|
1695
|
+
*
|
|
1696
|
+
* - -1: The version of 'self' is either less than 'frontiers' or is non-comparable (parallel) to 'frontiers',
|
|
1697
|
+
* indicating that it is not definitively less than 'frontiers'.
|
|
1698
|
+
* - 0: The version of 'self' is equal to 'frontiers'.
|
|
1699
|
+
* - 1: The version of 'self' is greater than 'frontiers'.
|
|
1700
|
+
*
|
|
1701
|
+
* # Internal
|
|
1702
|
+
*
|
|
1703
|
+
* Frontiers cannot be compared without the history of the OpLog.
|
|
1704
|
+
* @param {({ peer: PeerID, counter: number })[]} frontiers
|
|
1705
|
+
* @returns {number}
|
|
1706
|
+
*/
|
|
1707
|
+
cmpWithFrontiers(frontiers: ({ peer: PeerID, counter: number })[]): number;
|
|
1708
|
+
/**
|
|
1709
|
+
* Compare the ordering of two Frontiers.
|
|
1710
|
+
*
|
|
1711
|
+
* It's assumed that both Frontiers are included by the doc. Otherwise, an error will be thrown.
|
|
1712
|
+
*
|
|
1713
|
+
* Return value:
|
|
1714
|
+
*
|
|
1715
|
+
* - -1: a < b
|
|
1716
|
+
* - 0: a == b
|
|
1717
|
+
* - 1: a > b
|
|
1718
|
+
* - undefined: a ∥ b: a and b are concurrent
|
|
1719
|
+
* @param {({ peer: PeerID, counter: number })[]} a
|
|
1720
|
+
* @param {({ peer: PeerID, counter: number })[]} b
|
|
1721
|
+
* @returns {-1 | 1 | 0 | undefined}
|
|
1722
|
+
*/
|
|
1723
|
+
cmpFrontiers(a: ({ peer: PeerID, counter: number })[], b: ({ peer: PeerID, counter: number })[]): -1 | 1 | 0 | undefined;
|
|
1724
|
+
/**
|
|
1725
|
+
* Export the snapshot of current version.
|
|
1726
|
+
* It includes all the history and the document state
|
|
1727
|
+
*
|
|
1728
|
+
* @deprecated Use `export({mode: "snapshot"})` instead
|
|
1729
|
+
* @returns {Uint8Array}
|
|
1730
|
+
*/
|
|
1731
|
+
exportSnapshot(): Uint8Array;
|
|
1732
|
+
/**
|
|
1733
|
+
* Export the document based on the specified ExportMode.
|
|
1734
|
+
*
|
|
1735
|
+
* @param mode - The export mode to use. Can be one of:
|
|
1736
|
+
* - `{ mode: "snapshot" }`: Export a full snapshot of the document.
|
|
1737
|
+
* - `{ mode: "update", from?: VersionVector }`: Export updates from the given version vector.
|
|
1738
|
+
* - `{ mode: "updates-in-range", spans: { id: ID, len: number }[] }`: Export updates within the specified ID spans.
|
|
1739
|
+
* - `{ mode: "shallow-snapshot", frontiers: Frontiers }`: Export a garbage-collected snapshot up to the given frontiers.
|
|
1740
|
+
*
|
|
1741
|
+
* @returns A byte array containing the exported data.
|
|
1742
|
+
*
|
|
1743
|
+
* @example
|
|
1744
|
+
* ```ts
|
|
1745
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
1746
|
+
*
|
|
1747
|
+
* const doc = new LoroDoc();
|
|
1748
|
+
* doc.setPeerId("1");
|
|
1749
|
+
* doc.getText("text").update("Hello World");
|
|
1750
|
+
*
|
|
1751
|
+
* // Export a full snapshot
|
|
1752
|
+
* const snapshotBytes = doc.export({ mode: "snapshot" });
|
|
1753
|
+
*
|
|
1754
|
+
* // Export updates from a specific version
|
|
1755
|
+
* const vv = doc.oplogVersion();
|
|
1756
|
+
* doc.getText("text").update("Hello Loro");
|
|
1757
|
+
* const updateBytes = doc.export({ mode: "update", from: vv });
|
|
1758
|
+
*
|
|
1759
|
+
* // Export a shallow snapshot that only includes the history since the frontiers
|
|
1760
|
+
* const shallowBytes = doc.export({ mode: "shallow-snapshot", frontiers: doc.oplogFrontiers() });
|
|
1761
|
+
*
|
|
1762
|
+
* // Export updates within specific ID spans
|
|
1763
|
+
* const spanBytes = doc.export({
|
|
1764
|
+
* mode: "updates-in-range",
|
|
1765
|
+
* spans: [{ id: { peer: "1", counter: 0 }, len: 10 }]
|
|
1766
|
+
* });
|
|
1767
|
+
* ```
|
|
1768
|
+
* @param {ExportMode} mode
|
|
1769
|
+
* @returns {Uint8Array}
|
|
1770
|
+
*/
|
|
1771
|
+
export(mode: ExportMode): Uint8Array;
|
|
1772
|
+
/**
|
|
1773
|
+
* Export updates in the given range in JSON format.
|
|
1774
|
+
* @param {VersionVector | undefined} [start_vv]
|
|
1775
|
+
* @param {VersionVector | undefined} [end_vv]
|
|
1776
|
+
* @returns {JsonSchema}
|
|
1777
|
+
*/
|
|
1778
|
+
exportJsonUpdates(start_vv?: VersionVector, end_vv?: VersionVector): JsonSchema;
|
|
1779
|
+
/**
|
|
1780
|
+
* Import updates from the JSON format.
|
|
1781
|
+
*
|
|
1782
|
+
* only supports backward compatibility but not forward compatibility.
|
|
1783
|
+
* @param {string | JsonSchema} json
|
|
1784
|
+
* @returns {ImportStatus}
|
|
1785
|
+
*/
|
|
1786
|
+
importJsonUpdates(json: string | JsonSchema): ImportStatus;
|
|
1787
|
+
/**
|
|
1788
|
+
* Import snapshot or updates into current doc.
|
|
1789
|
+
*
|
|
1790
|
+
* Note:
|
|
1791
|
+
* - Updates within the current version will be ignored
|
|
1792
|
+
* - Updates with missing dependencies will be pending until the dependencies are received
|
|
1793
|
+
*
|
|
1794
|
+
* @example
|
|
1795
|
+
* ```ts
|
|
1796
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1797
|
+
*
|
|
1798
|
+
* const doc = new LoroDoc();
|
|
1799
|
+
* const text = doc.getText("text");
|
|
1800
|
+
* text.insert(0, "Hello");
|
|
1801
|
+
* // get all updates of the doc
|
|
1802
|
+
* const updates = doc.export({ mode: "update" });
|
|
1803
|
+
* const snapshot = doc.export({ mode: "snapshot" });
|
|
1804
|
+
* const doc2 = new LoroDoc();
|
|
1805
|
+
* // import snapshot
|
|
1806
|
+
* doc2.import(snapshot);
|
|
1807
|
+
* // or import updates
|
|
1808
|
+
* doc2.import(updates);
|
|
1809
|
+
* ```
|
|
1810
|
+
* @param {Uint8Array} update_or_snapshot
|
|
1811
|
+
* @returns {ImportStatus}
|
|
1812
|
+
*/
|
|
1813
|
+
import(update_or_snapshot: Uint8Array): ImportStatus;
|
|
1814
|
+
/**
|
|
1815
|
+
* Import a batch of updates.
|
|
1816
|
+
*
|
|
1817
|
+
* It's more efficient than importing updates one by one.
|
|
1818
|
+
*
|
|
1819
|
+
* @example
|
|
1820
|
+
* ```ts
|
|
1821
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1822
|
+
*
|
|
1823
|
+
* const doc = new LoroDoc();
|
|
1824
|
+
* const text = doc.getText("text");
|
|
1825
|
+
* text.insert(0, "Hello");
|
|
1826
|
+
* const updates = doc.export({ mode: "update" });
|
|
1827
|
+
* const snapshot = doc.export({ mode: "snapshot" });
|
|
1828
|
+
* const doc2 = new LoroDoc();
|
|
1829
|
+
* doc2.importUpdateBatch([snapshot, updates]);
|
|
1830
|
+
* ```
|
|
1831
|
+
* @param {Array<any>} data
|
|
1832
|
+
*/
|
|
1833
|
+
importUpdateBatch(data: Array<any>): void;
|
|
1834
|
+
/**
|
|
1835
|
+
* Get the shallow json format of the document state.
|
|
1836
|
+
*
|
|
1837
|
+
* @example
|
|
1838
|
+
* ```ts
|
|
1839
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1840
|
+
*
|
|
1841
|
+
* const doc = new LoroDoc();
|
|
1842
|
+
* const list = doc.getList("list");
|
|
1843
|
+
* const tree = doc.getTree("tree");
|
|
1844
|
+
* const map = doc.getMap("map");
|
|
1845
|
+
* const shallowValue = doc.getShallowValue();
|
|
1846
|
+
* /*
|
|
1847
|
+
* {"list": ..., "tree": ..., "map": ...}
|
|
1848
|
+
* *\/
|
|
1849
|
+
* console.log(shallowValue);
|
|
1850
|
+
* ```
|
|
1851
|
+
* @returns {any}
|
|
1852
|
+
*/
|
|
1853
|
+
getShallowValue(): any;
|
|
1854
|
+
/**
|
|
1855
|
+
* Get the json format of the entire document state.
|
|
1856
|
+
*
|
|
1857
|
+
* @example
|
|
1858
|
+
* ```ts
|
|
1859
|
+
* import { LoroDoc, LoroText, LoroMap } from "loro-crdt";
|
|
1860
|
+
*
|
|
1861
|
+
* const doc = new LoroDoc();
|
|
1862
|
+
* const list = doc.getList("list");
|
|
1863
|
+
* list.insert(0, "Hello");
|
|
1864
|
+
* const text = list.insertContainer(0, new LoroText());
|
|
1865
|
+
* text.insert(0, "Hello");
|
|
1866
|
+
* const map = list.insertContainer(1, new LoroMap());
|
|
1867
|
+
* map.set("foo", "bar");
|
|
1868
|
+
* /*
|
|
1869
|
+
* {"list": ["Hello", {"foo": "bar"}]}
|
|
1870
|
+
* *\/
|
|
1871
|
+
* console.log(doc.toJSON());
|
|
1872
|
+
* ```
|
|
1873
|
+
* @returns {any}
|
|
1874
|
+
*/
|
|
1875
|
+
toJSON(): any;
|
|
1876
|
+
/**
|
|
1877
|
+
* Debug the size of the history
|
|
1878
|
+
*/
|
|
1879
|
+
debugHistory(): void;
|
|
1880
|
+
/**
|
|
1881
|
+
* Get all of changes in the oplog.
|
|
1882
|
+
*
|
|
1883
|
+
* Note: this method is expensive when the oplog is large. O(n)
|
|
1884
|
+
*
|
|
1885
|
+
* @example
|
|
1886
|
+
* ```ts
|
|
1887
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
1888
|
+
*
|
|
1889
|
+
* const doc = new LoroDoc();
|
|
1890
|
+
* const text = doc.getText("text");
|
|
1891
|
+
* text.insert(0, "Hello");
|
|
1892
|
+
* const changes = doc.getAllChanges();
|
|
1893
|
+
*
|
|
1894
|
+
* for (let [peer, c] of changes.entries()){
|
|
1895
|
+
* console.log("peer: ", peer);
|
|
1896
|
+
* for (let change of c){
|
|
1897
|
+
* console.log("change: ", change);
|
|
1898
|
+
* }
|
|
1899
|
+
* }
|
|
1900
|
+
* ```
|
|
1901
|
+
* @returns {Map<PeerID, Change[]>}
|
|
1902
|
+
*/
|
|
1903
|
+
getAllChanges(): Map<PeerID, Change[]>;
|
|
1904
|
+
/**
|
|
1905
|
+
* Get the change that contains the specific ID
|
|
1906
|
+
* @param {{ peer: PeerID, counter: number }} id
|
|
1907
|
+
* @returns {Change}
|
|
1908
|
+
*/
|
|
1909
|
+
getChangeAt(id: { peer: PeerID, counter: number }): Change;
|
|
1910
|
+
/**
|
|
1911
|
+
* Get the change of with specific peer_id and lamport <= given lamport
|
|
1912
|
+
* @param {string} peer_id
|
|
1913
|
+
* @param {number} lamport
|
|
1914
|
+
* @returns {Change | undefined}
|
|
1915
|
+
*/
|
|
1916
|
+
getChangeAtLamport(peer_id: string, lamport: number): Change | undefined;
|
|
1917
|
+
/**
|
|
1918
|
+
* Get all ops of the change that contains the specific ID
|
|
1919
|
+
* @param {{ peer: PeerID, counter: number }} id
|
|
1920
|
+
* @returns {any[]}
|
|
1921
|
+
*/
|
|
1922
|
+
getOpsInChange(id: { peer: PeerID, counter: number }): any[];
|
|
1923
|
+
/**
|
|
1924
|
+
* Convert frontiers to a version vector
|
|
1925
|
+
*
|
|
1926
|
+
* Learn more about frontiers and version vector [here](https://loro.dev/docs/advanced/version_deep_dive)
|
|
1927
|
+
*
|
|
1928
|
+
* @example
|
|
1929
|
+
* ```ts
|
|
1930
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1931
|
+
*
|
|
1932
|
+
* const doc = new LoroDoc();
|
|
1933
|
+
* const text = doc.getText("text");
|
|
1934
|
+
* text.insert(0, "Hello");
|
|
1935
|
+
* const frontiers = doc.frontiers();
|
|
1936
|
+
* const version = doc.frontiersToVV(frontiers);
|
|
1937
|
+
* ```
|
|
1938
|
+
* @param {({ peer: PeerID, counter: number })[]} frontiers
|
|
1939
|
+
* @returns {VersionVector}
|
|
1940
|
+
*/
|
|
1941
|
+
frontiersToVV(frontiers: ({ peer: PeerID, counter: number })[]): VersionVector;
|
|
1942
|
+
/**
|
|
1943
|
+
* Convert a version vector to frontiers
|
|
1944
|
+
*
|
|
1945
|
+
* @example
|
|
1946
|
+
* ```ts
|
|
1947
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1948
|
+
*
|
|
1949
|
+
* const doc = new LoroDoc();
|
|
1950
|
+
* const text = doc.getText("text");
|
|
1951
|
+
* text.insert(0, "Hello");
|
|
1952
|
+
* const version = doc.version();
|
|
1953
|
+
* const frontiers = doc.vvToFrontiers(version);
|
|
1954
|
+
* ```
|
|
1955
|
+
* @param {VersionVector} vv
|
|
1956
|
+
* @returns {{ peer: PeerID, counter: number }[]}
|
|
1957
|
+
*/
|
|
1958
|
+
vvToFrontiers(vv: VersionVector): { peer: PeerID, counter: number }[];
|
|
1959
|
+
/**
|
|
1960
|
+
* Get the value or container at the given path
|
|
1961
|
+
*
|
|
1962
|
+
* @example
|
|
1963
|
+
* ```ts
|
|
1964
|
+
* import { LoroDoc } from "loro-crdt";
|
|
1965
|
+
*
|
|
1966
|
+
* const doc = new LoroDoc();
|
|
1967
|
+
* const map = doc.getMap("map");
|
|
1968
|
+
* map.set("key", 1);
|
|
1969
|
+
* console.log(doc.getByPath("map/key")); // 1
|
|
1970
|
+
* console.log(doc.getByPath("map")); // LoroMap
|
|
1971
|
+
* ```
|
|
1972
|
+
* @param {string} path
|
|
1973
|
+
* @returns {Value | Container | undefined}
|
|
1974
|
+
*/
|
|
1975
|
+
getByPath(path: string): Value | Container | undefined;
|
|
1976
|
+
/**
|
|
1977
|
+
* Get the absolute position of the given Cursor
|
|
1978
|
+
*
|
|
1979
|
+
* @example
|
|
1980
|
+
* ```ts
|
|
1981
|
+
* const doc = new LoroDoc();
|
|
1982
|
+
* const text = doc.getText("text");
|
|
1983
|
+
* text.insert(0, "123");
|
|
1984
|
+
* const pos0 = text.getCursor(0, 0);
|
|
1985
|
+
* {
|
|
1986
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
1987
|
+
* expect(ans.offset).toBe(0);
|
|
1988
|
+
* }
|
|
1989
|
+
* text.insert(0, "1");
|
|
1990
|
+
* {
|
|
1991
|
+
* const ans = doc.getCursorPos(pos0!);
|
|
1992
|
+
* expect(ans.offset).toBe(1);
|
|
1993
|
+
* }
|
|
1994
|
+
* ```
|
|
1995
|
+
* @param {Cursor} cursor
|
|
1996
|
+
* @returns {{ update?: Cursor, offset: number, side: Side }}
|
|
1997
|
+
*/
|
|
1998
|
+
getCursorPos(cursor: Cursor): { update?: Cursor, offset: number, side: Side };
|
|
1999
|
+
/**
|
|
2000
|
+
* Peer ID of the current writer.
|
|
2001
|
+
*/
|
|
2002
|
+
readonly peerId: bigint;
|
|
2003
|
+
/**
|
|
2004
|
+
* Get peer id in decimal string.
|
|
2005
|
+
*/
|
|
2006
|
+
readonly peerIdStr: PeerID;
|
|
2007
|
+
}
|
|
2008
|
+
/**
|
|
2009
|
+
* The handler of a list container.
|
|
2010
|
+
*
|
|
2011
|
+
* Learn more at https://loro.dev/docs/tutorial/list
|
|
2012
|
+
*/
|
|
2013
|
+
export class LoroList {
|
|
2014
|
+
free(): void;
|
|
2015
|
+
/**
|
|
2016
|
+
* Create a new detached LoroList (not attached to any LoroDoc).
|
|
2017
|
+
*
|
|
2018
|
+
* The edits on a detached container will not be persisted.
|
|
2019
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
2020
|
+
*/
|
|
2021
|
+
constructor();
|
|
2022
|
+
/**
|
|
2023
|
+
* "List"
|
|
2024
|
+
* @returns {'List'}
|
|
2025
|
+
*/
|
|
2026
|
+
kind(): 'List';
|
|
2027
|
+
/**
|
|
2028
|
+
* Delete elements from index to index + len.
|
|
2029
|
+
*
|
|
2030
|
+
* @example
|
|
2031
|
+
* ```ts
|
|
2032
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2033
|
+
*
|
|
2034
|
+
* const doc = new LoroDoc();
|
|
2035
|
+
* const list = doc.getList("list");
|
|
2036
|
+
* list.insert(0, 100);
|
|
2037
|
+
* list.delete(0, 1);
|
|
2038
|
+
* console.log(list.value); // []
|
|
2039
|
+
* ```
|
|
2040
|
+
* @param {number} index
|
|
2041
|
+
* @param {number} len
|
|
2042
|
+
*/
|
|
2043
|
+
delete(index: number, len: number): void;
|
|
2044
|
+
/**
|
|
2045
|
+
* Get elements of the list. If the type of a element is a container, it will be
|
|
2046
|
+
* resolved recursively.
|
|
2047
|
+
*
|
|
2048
|
+
* @example
|
|
2049
|
+
* ```ts
|
|
2050
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
2051
|
+
*
|
|
2052
|
+
* const doc = new LoroDoc();
|
|
2053
|
+
* const list = doc.getList("list");
|
|
2054
|
+
* list.insert(0, 100);
|
|
2055
|
+
* const text = list.insertContainer(1, new LoroText());
|
|
2056
|
+
* text.insert(0, "Hello");
|
|
2057
|
+
* console.log(list.toJSON()); // [100, "Hello"];
|
|
2058
|
+
* ```
|
|
2059
|
+
* @returns {any}
|
|
2060
|
+
*/
|
|
2061
|
+
toJSON(): any;
|
|
2062
|
+
/**
|
|
2063
|
+
* Get the parent container.
|
|
2064
|
+
*
|
|
2065
|
+
* - The parent container of the root tree is `undefined`.
|
|
2066
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2067
|
+
* the WASM boundary.
|
|
2068
|
+
* @returns {Container | undefined}
|
|
2069
|
+
*/
|
|
2070
|
+
parent(): Container | undefined;
|
|
2071
|
+
/**
|
|
2072
|
+
* Whether the container is attached to a document.
|
|
2073
|
+
*
|
|
2074
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
2075
|
+
* @returns {boolean}
|
|
2076
|
+
*/
|
|
2077
|
+
isAttached(): boolean;
|
|
2078
|
+
/**
|
|
2079
|
+
* Get the attached container associated with this.
|
|
2080
|
+
*
|
|
2081
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2082
|
+
* @returns {LoroList | undefined}
|
|
2083
|
+
*/
|
|
2084
|
+
getAttached(): LoroList | undefined;
|
|
2085
|
+
/**
|
|
2086
|
+
* Pop a value from the end of the list.
|
|
2087
|
+
* @returns {Value | undefined}
|
|
2088
|
+
*/
|
|
2089
|
+
pop(): Value | undefined;
|
|
2090
|
+
/**
|
|
2091
|
+
* Delete all elements in the list.
|
|
2092
|
+
*/
|
|
2093
|
+
clear(): void;
|
|
2094
|
+
/**
|
|
2095
|
+
* Get the id of this container.
|
|
2096
|
+
*/
|
|
2097
|
+
readonly id: ContainerID;
|
|
2098
|
+
/**
|
|
2099
|
+
* Get the length of list.
|
|
2100
|
+
*
|
|
2101
|
+
* @example
|
|
2102
|
+
* ```ts
|
|
2103
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2104
|
+
*
|
|
2105
|
+
* const doc = new LoroDoc();
|
|
2106
|
+
* const list = doc.getList("list");
|
|
2107
|
+
* list.insert(0, 100);
|
|
2108
|
+
* list.insert(1, "foo");
|
|
2109
|
+
* list.insert(2, true);
|
|
2110
|
+
* console.log(list.length); // 3
|
|
2111
|
+
* ```
|
|
2112
|
+
*/
|
|
2113
|
+
readonly length: number;
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* The handler of a map container.
|
|
2117
|
+
*
|
|
2118
|
+
* Learn more at https://loro.dev/docs/tutorial/map
|
|
2119
|
+
*/
|
|
2120
|
+
export class LoroMap {
|
|
2121
|
+
free(): void;
|
|
2122
|
+
/**
|
|
2123
|
+
* Create a new detached LoroMap (not attached to any LoroDoc).
|
|
2124
|
+
*
|
|
2125
|
+
* The edits on a detached container will not be persisted.
|
|
2126
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
2127
|
+
*/
|
|
2128
|
+
constructor();
|
|
2129
|
+
/**
|
|
2130
|
+
* "Map"
|
|
2131
|
+
* @returns {'Map'}
|
|
2132
|
+
*/
|
|
2133
|
+
kind(): 'Map';
|
|
2134
|
+
/**
|
|
2135
|
+
* Remove the key from the map.
|
|
2136
|
+
*
|
|
2137
|
+
* @example
|
|
2138
|
+
* ```ts
|
|
2139
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2140
|
+
*
|
|
2141
|
+
* const doc = new LoroDoc();
|
|
2142
|
+
* const map = doc.getMap("map");
|
|
2143
|
+
* map.set("foo", "bar");
|
|
2144
|
+
* map.delete("foo");
|
|
2145
|
+
* ```
|
|
2146
|
+
* @param {string} key
|
|
2147
|
+
*/
|
|
2148
|
+
delete(key: string): void;
|
|
2149
|
+
/**
|
|
2150
|
+
* Get the keys of the map.
|
|
2151
|
+
*
|
|
2152
|
+
* @example
|
|
2153
|
+
* ```ts
|
|
2154
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2155
|
+
*
|
|
2156
|
+
* const doc = new LoroDoc();
|
|
2157
|
+
* const map = doc.getMap("map");
|
|
2158
|
+
* map.set("foo", "bar");
|
|
2159
|
+
* map.set("baz", "bar");
|
|
2160
|
+
* const keys = map.keys(); // ["foo", "baz"]
|
|
2161
|
+
* ```
|
|
2162
|
+
* @returns {any[]}
|
|
2163
|
+
*/
|
|
2164
|
+
keys(): any[];
|
|
2165
|
+
/**
|
|
2166
|
+
* Get the values of the map. If the value is a child container, the corresponding
|
|
2167
|
+
* `Container` will be returned.
|
|
2168
|
+
*
|
|
2169
|
+
* @example
|
|
2170
|
+
* ```ts
|
|
2171
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2172
|
+
*
|
|
2173
|
+
* const doc = new LoroDoc();
|
|
2174
|
+
* const map = doc.getMap("map");
|
|
2175
|
+
* map.set("foo", "bar");
|
|
2176
|
+
* map.set("baz", "bar");
|
|
2177
|
+
* const values = map.values(); // ["bar", "bar"]
|
|
2178
|
+
* ```
|
|
2179
|
+
* @returns {any[]}
|
|
2180
|
+
*/
|
|
2181
|
+
values(): any[];
|
|
2182
|
+
/**
|
|
2183
|
+
* Get the entries of the map. If the value is a child container, the corresponding
|
|
2184
|
+
* `Container` will be returned.
|
|
2185
|
+
*
|
|
2186
|
+
* @example
|
|
2187
|
+
* ```ts
|
|
2188
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2189
|
+
*
|
|
2190
|
+
* const doc = new LoroDoc();
|
|
2191
|
+
* const map = doc.getMap("map");
|
|
2192
|
+
* map.set("foo", "bar");
|
|
2193
|
+
* map.set("baz", "bar");
|
|
2194
|
+
* const entries = map.entries(); // [["foo", "bar"], ["baz", "bar"]]
|
|
2195
|
+
* ```
|
|
2196
|
+
* @returns {([string, Value | Container])[]}
|
|
2197
|
+
*/
|
|
2198
|
+
entries(): ([string, Value | Container])[];
|
|
2199
|
+
/**
|
|
2200
|
+
* Get the keys and the values. If the type of value is a child container,
|
|
2201
|
+
* it will be resolved recursively.
|
|
2202
|
+
*
|
|
2203
|
+
* @example
|
|
2204
|
+
* ```ts
|
|
2205
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
2206
|
+
*
|
|
2207
|
+
* const doc = new LoroDoc();
|
|
2208
|
+
* const map = doc.getMap("map");
|
|
2209
|
+
* map.set("foo", "bar");
|
|
2210
|
+
* const text = map.setContainer("text", new LoroText());
|
|
2211
|
+
* text.insert(0, "Hello");
|
|
2212
|
+
* console.log(map.toJSON()); // {"foo": "bar", "text": "Hello"}
|
|
2213
|
+
* ```
|
|
2214
|
+
* @returns {any}
|
|
2215
|
+
*/
|
|
2216
|
+
toJSON(): any;
|
|
2217
|
+
/**
|
|
2218
|
+
* Get the parent container.
|
|
2219
|
+
*
|
|
2220
|
+
* - The parent container of the root tree is `undefined`.
|
|
2221
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2222
|
+
* the WASM boundary.
|
|
2223
|
+
* @returns {Container | undefined}
|
|
2224
|
+
*/
|
|
2225
|
+
parent(): Container | undefined;
|
|
2226
|
+
/**
|
|
2227
|
+
* Whether the container is attached to a document.
|
|
2228
|
+
*
|
|
2229
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
2230
|
+
* @returns {boolean}
|
|
2231
|
+
*/
|
|
2232
|
+
isAttached(): boolean;
|
|
2233
|
+
/**
|
|
2234
|
+
* Get the attached container associated with this.
|
|
2235
|
+
*
|
|
2236
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2237
|
+
* @returns {LoroMap | undefined}
|
|
2238
|
+
*/
|
|
2239
|
+
getAttached(): LoroMap | undefined;
|
|
2240
|
+
/**
|
|
2241
|
+
* Delete all key-value pairs in the map.
|
|
2242
|
+
*/
|
|
2243
|
+
clear(): void;
|
|
2244
|
+
/**
|
|
2245
|
+
* The container id of this handler.
|
|
2246
|
+
*/
|
|
2247
|
+
readonly id: ContainerID;
|
|
2248
|
+
/**
|
|
2249
|
+
* Get the size of the map.
|
|
2250
|
+
*
|
|
2251
|
+
* @example
|
|
2252
|
+
* ```ts
|
|
2253
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2254
|
+
*
|
|
2255
|
+
* const doc = new LoroDoc();
|
|
2256
|
+
* const map = doc.getMap("map");
|
|
2257
|
+
* map.set("foo", "bar");
|
|
2258
|
+
* console.log(map.size); // 1
|
|
2259
|
+
* ```
|
|
2260
|
+
*/
|
|
2261
|
+
readonly size: number;
|
|
2262
|
+
}
|
|
2263
|
+
/**
|
|
2264
|
+
* The handler of a list container.
|
|
2265
|
+
*
|
|
2266
|
+
* Learn more at https://loro.dev/docs/tutorial/list
|
|
2267
|
+
*/
|
|
2268
|
+
export class LoroMovableList {
|
|
2269
|
+
free(): void;
|
|
2270
|
+
/**
|
|
2271
|
+
* Create a new detached LoroMovableList (not attached to any LoroDoc).
|
|
2272
|
+
*
|
|
2273
|
+
* The edits on a detached container will not be persisted.
|
|
2274
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
2275
|
+
*/
|
|
2276
|
+
constructor();
|
|
2277
|
+
/**
|
|
2278
|
+
* "MovableList"
|
|
2279
|
+
* @returns {'MovableList'}
|
|
2280
|
+
*/
|
|
2281
|
+
kind(): 'MovableList';
|
|
2282
|
+
/**
|
|
2283
|
+
* Delete elements from index to index + len.
|
|
2284
|
+
*
|
|
2285
|
+
* @example
|
|
2286
|
+
* ```ts
|
|
2287
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2288
|
+
*
|
|
2289
|
+
* const doc = new LoroDoc();
|
|
2290
|
+
* const list = doc.getList("list");
|
|
2291
|
+
* list.insert(0, 100);
|
|
2292
|
+
* list.delete(0, 1);
|
|
2293
|
+
* console.log(list.value); // []
|
|
2294
|
+
* ```
|
|
2295
|
+
* @param {number} index
|
|
2296
|
+
* @param {number} len
|
|
2297
|
+
*/
|
|
2298
|
+
delete(index: number, len: number): void;
|
|
2299
|
+
/**
|
|
2300
|
+
* Get elements of the list. If the type of a element is a container, it will be
|
|
2301
|
+
* resolved recursively.
|
|
2302
|
+
*
|
|
2303
|
+
* @example
|
|
2304
|
+
* ```ts
|
|
2305
|
+
* import { LoroDoc, LoroText } from "loro-crdt";
|
|
2306
|
+
*
|
|
2307
|
+
* const doc = new LoroDoc();
|
|
2308
|
+
* const list = doc.getList("list");
|
|
2309
|
+
* list.insert(0, 100);
|
|
2310
|
+
* const text = list.insertContainer(1, new LoroText());
|
|
2311
|
+
* text.insert(0, "Hello");
|
|
2312
|
+
* console.log(list.toJSON()); // [100, "Hello"];
|
|
2313
|
+
* ```
|
|
2314
|
+
* @returns {any}
|
|
2315
|
+
*/
|
|
2316
|
+
toJSON(): any;
|
|
2317
|
+
/**
|
|
2318
|
+
* Get the parent container.
|
|
2319
|
+
*
|
|
2320
|
+
* - The parent container of the root tree is `undefined`.
|
|
2321
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2322
|
+
* the WASM boundary.
|
|
2323
|
+
* @returns {Container | undefined}
|
|
2324
|
+
*/
|
|
2325
|
+
parent(): Container | undefined;
|
|
2326
|
+
/**
|
|
2327
|
+
* Whether the container is attached to a document.
|
|
2328
|
+
*
|
|
2329
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
2330
|
+
* @returns {boolean}
|
|
2331
|
+
*/
|
|
2332
|
+
isAttached(): boolean;
|
|
2333
|
+
/**
|
|
2334
|
+
* Get the attached container associated with this.
|
|
2335
|
+
*
|
|
2336
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2337
|
+
* @returns {LoroList | undefined}
|
|
2338
|
+
*/
|
|
2339
|
+
getAttached(): LoroList | undefined;
|
|
2340
|
+
/**
|
|
2341
|
+
* Move the element from `from` to `to`.
|
|
2342
|
+
*
|
|
2343
|
+
* The new position of the element will be `to`.
|
|
2344
|
+
* Move the element from `from` to `to`.
|
|
2345
|
+
*
|
|
2346
|
+
* The new position of the element will be `to`. This method is optimized to prevent redundant
|
|
2347
|
+
* operations that might occur with a naive remove and insert approach. Specifically, it avoids
|
|
2348
|
+
* creating surplus values in the list, unlike a delete followed by an insert, which can lead to
|
|
2349
|
+
* additional values in cases of concurrent edits. This ensures more efficient and accurate
|
|
2350
|
+
* operations in a MovableList.
|
|
2351
|
+
* @param {number} from
|
|
2352
|
+
* @param {number} to
|
|
2353
|
+
*/
|
|
2354
|
+
move(from: number, to: number): void;
|
|
2355
|
+
/**
|
|
2356
|
+
* Pop a value from the end of the list.
|
|
2357
|
+
* @returns {Value | undefined}
|
|
2358
|
+
*/
|
|
2359
|
+
pop(): Value | undefined;
|
|
2360
|
+
/**
|
|
2361
|
+
* Delete all elements in the list.
|
|
2362
|
+
*/
|
|
2363
|
+
clear(): void;
|
|
2364
|
+
/**
|
|
2365
|
+
* Get the id of this container.
|
|
2366
|
+
*/
|
|
2367
|
+
readonly id: ContainerID;
|
|
2368
|
+
/**
|
|
2369
|
+
* Get the length of list.
|
|
2370
|
+
*
|
|
2371
|
+
* @example
|
|
2372
|
+
* ```ts
|
|
2373
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2374
|
+
*
|
|
2375
|
+
* const doc = new LoroDoc();
|
|
2376
|
+
* const list = doc.getList("list");
|
|
2377
|
+
* list.insert(0, 100);
|
|
2378
|
+
* list.insert(1, "foo");
|
|
2379
|
+
* list.insert(2, true);
|
|
2380
|
+
* console.log(list.length); // 3
|
|
2381
|
+
* ```
|
|
2382
|
+
*/
|
|
2383
|
+
readonly length: number;
|
|
2384
|
+
}
|
|
2385
|
+
/**
|
|
2386
|
+
* The handler of a text container. It supports rich text CRDT.
|
|
2387
|
+
*
|
|
2388
|
+
* Learn more at https://loro.dev/docs/tutorial/text
|
|
2389
|
+
*/
|
|
2390
|
+
export class LoroText {
|
|
2391
|
+
free(): void;
|
|
2392
|
+
/**
|
|
2393
|
+
* Create a new detached LoroText (not attached to any LoroDoc).
|
|
2394
|
+
*
|
|
2395
|
+
* The edits on a detached container will not be persisted.
|
|
2396
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
2397
|
+
*/
|
|
2398
|
+
constructor();
|
|
2399
|
+
/**
|
|
2400
|
+
* "Text"
|
|
2401
|
+
* @returns {'Text'}
|
|
2402
|
+
*/
|
|
2403
|
+
kind(): 'Text';
|
|
2404
|
+
/**
|
|
2405
|
+
* Iterate each span(internal storage unit) of the text.
|
|
2406
|
+
*
|
|
2407
|
+
* The callback function will be called for each span in the text.
|
|
2408
|
+
* If the callback returns `false`, the iteration will stop.
|
|
2409
|
+
*
|
|
2410
|
+
* @example
|
|
2411
|
+
* ```ts
|
|
2412
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2413
|
+
*
|
|
2414
|
+
* const doc = new LoroDoc();
|
|
2415
|
+
* const text = doc.getText("text");
|
|
2416
|
+
* text.insert(0, "Hello");
|
|
2417
|
+
* text.iter((str) => (console.log(str), true));
|
|
2418
|
+
* ```
|
|
2419
|
+
* @param {Function} callback
|
|
2420
|
+
*/
|
|
2421
|
+
iter(callback: Function): void;
|
|
2422
|
+
/**
|
|
2423
|
+
* Update the current text to the target text.
|
|
2424
|
+
*
|
|
2425
|
+
* It will calculate the minimal difference and apply it to the current text.
|
|
2426
|
+
* It uses Myers' diff algorithm to compute the optimal difference.
|
|
2427
|
+
*
|
|
2428
|
+
* This could take a long time for large texts (e.g. > 50_000 characters).
|
|
2429
|
+
* In that case, you should use `updateByLine` instead.
|
|
2430
|
+
*
|
|
2431
|
+
* @example
|
|
2432
|
+
* ```ts
|
|
2433
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2434
|
+
*
|
|
2435
|
+
* const doc = new LoroDoc();
|
|
2436
|
+
* const text = doc.getText("text");
|
|
2437
|
+
* text.insert(0, "Hello");
|
|
2438
|
+
* text.update("Hello World");
|
|
2439
|
+
* console.log(text.toString()); // "Hello World"
|
|
2440
|
+
* ```
|
|
2441
|
+
* @param {string} text
|
|
2442
|
+
*/
|
|
2443
|
+
update(text: string): void;
|
|
2444
|
+
/**
|
|
2445
|
+
* Update the current text to the target text, the difference is calculated line by line.
|
|
2446
|
+
*
|
|
2447
|
+
* It uses Myers' diff algorithm to compute the optimal difference.
|
|
2448
|
+
* @param {string} text
|
|
2449
|
+
*/
|
|
2450
|
+
updateByLine(text: string): void;
|
|
2451
|
+
/**
|
|
2452
|
+
* Insert the string at the given index (utf-16 index).
|
|
2453
|
+
*
|
|
2454
|
+
* @example
|
|
2455
|
+
* ```ts
|
|
2456
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2457
|
+
*
|
|
2458
|
+
* const doc = new LoroDoc();
|
|
2459
|
+
* const text = doc.getText("text");
|
|
2460
|
+
* text.insert(0, "Hello");
|
|
2461
|
+
* ```
|
|
2462
|
+
* @param {number} index
|
|
2463
|
+
* @param {string} content
|
|
2464
|
+
*/
|
|
2465
|
+
insert(index: number, content: string): void;
|
|
2466
|
+
/**
|
|
2467
|
+
* Get a string slice (utf-16 index).
|
|
2468
|
+
*
|
|
2469
|
+
* @example
|
|
2470
|
+
* ```ts
|
|
2471
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2472
|
+
*
|
|
2473
|
+
* const doc = new LoroDoc();
|
|
2474
|
+
* const text = doc.getText("text");
|
|
2475
|
+
* text.insert(0, "Hello");
|
|
2476
|
+
* text.slice(0, 2); // "He"
|
|
2477
|
+
* ```
|
|
2478
|
+
* @param {number} start_index
|
|
2479
|
+
* @param {number} end_index
|
|
2480
|
+
* @returns {string}
|
|
2481
|
+
*/
|
|
2482
|
+
slice(start_index: number, end_index: number): string;
|
|
2483
|
+
/**
|
|
2484
|
+
* Get the character at the given position (utf-16 index).
|
|
2485
|
+
*
|
|
2486
|
+
* @example
|
|
2487
|
+
* ```ts
|
|
2488
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2489
|
+
*
|
|
2490
|
+
* const doc = new LoroDoc();
|
|
2491
|
+
* const text = doc.getText("text");
|
|
2492
|
+
* text.insert(0, "Hello");
|
|
2493
|
+
* text.charAt(0); // "H"
|
|
2494
|
+
* ```
|
|
2495
|
+
* @param {number} pos
|
|
2496
|
+
* @returns {string}
|
|
2497
|
+
*/
|
|
2498
|
+
charAt(pos: number): string;
|
|
2499
|
+
/**
|
|
2500
|
+
* Delete and return the string at the given range and insert a string at the same position (utf-16 index).
|
|
2501
|
+
*
|
|
2502
|
+
* @example
|
|
2503
|
+
* ```ts
|
|
2504
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2505
|
+
*
|
|
2506
|
+
* const doc = new LoroDoc();
|
|
2507
|
+
* const text = doc.getText("text");
|
|
2508
|
+
* text.insert(0, "Hello");
|
|
2509
|
+
* text.splice(2, 3, "llo"); // "llo"
|
|
2510
|
+
* ```
|
|
2511
|
+
* @param {number} pos
|
|
2512
|
+
* @param {number} len
|
|
2513
|
+
* @param {string} s
|
|
2514
|
+
* @returns {string}
|
|
2515
|
+
*/
|
|
2516
|
+
splice(pos: number, len: number, s: string): string;
|
|
2517
|
+
/**
|
|
2518
|
+
* Insert some string at utf-8 index.
|
|
2519
|
+
*
|
|
2520
|
+
* @example
|
|
2521
|
+
* ```ts
|
|
2522
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2523
|
+
*
|
|
2524
|
+
* const doc = new LoroDoc();
|
|
2525
|
+
* const text = doc.getText("text");
|
|
2526
|
+
* text.insertUtf8(0, "Hello");
|
|
2527
|
+
* ```
|
|
2528
|
+
* @param {number} index
|
|
2529
|
+
* @param {string} content
|
|
2530
|
+
*/
|
|
2531
|
+
insertUtf8(index: number, content: string): void;
|
|
2532
|
+
/**
|
|
2533
|
+
* Delete elements from index to index + len (utf-16 index).
|
|
2534
|
+
*
|
|
2535
|
+
* @example
|
|
2536
|
+
* ```ts
|
|
2537
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2538
|
+
*
|
|
2539
|
+
* const doc = new LoroDoc();
|
|
2540
|
+
* const text = doc.getText("text");
|
|
2541
|
+
* text.insert(0, "Hello");
|
|
2542
|
+
* text.delete(1, 3);
|
|
2543
|
+
* const s = text.toString();
|
|
2544
|
+
* console.log(s); // "Ho"
|
|
2545
|
+
* ```
|
|
2546
|
+
* @param {number} index
|
|
2547
|
+
* @param {number} len
|
|
2548
|
+
*/
|
|
2549
|
+
delete(index: number, len: number): void;
|
|
2550
|
+
/**
|
|
2551
|
+
* Delete elements from index to utf-8 index + len
|
|
2552
|
+
*
|
|
2553
|
+
* @example
|
|
2554
|
+
* ```ts
|
|
2555
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2556
|
+
*
|
|
2557
|
+
* const doc = new LoroDoc();
|
|
2558
|
+
* const text = doc.getText("text");
|
|
2559
|
+
* text.insertUtf8(0, "Hello");
|
|
2560
|
+
* text.deleteUtf8(1, 3);
|
|
2561
|
+
* const s = text.toString();
|
|
2562
|
+
* console.log(s); // "Ho"
|
|
2563
|
+
* ```
|
|
2564
|
+
* @param {number} index
|
|
2565
|
+
* @param {number} len
|
|
2566
|
+
*/
|
|
2567
|
+
deleteUtf8(index: number, len: number): void;
|
|
2568
|
+
/**
|
|
2569
|
+
* Mark a range of text with a key and a value (utf-16 index).
|
|
2570
|
+
*
|
|
2571
|
+
* > You should call `configTextStyle` before using `mark` and `unmark`.
|
|
2572
|
+
*
|
|
2573
|
+
* You can use it to create a highlight, make a range of text bold, or add a link to a range of text.
|
|
2574
|
+
*
|
|
2575
|
+
* Note: this is not suitable for unmergeable annotations like comments.
|
|
2576
|
+
*
|
|
2577
|
+
* @example
|
|
2578
|
+
* ```ts
|
|
2579
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2580
|
+
*
|
|
2581
|
+
* const doc = new LoroDoc();
|
|
2582
|
+
* doc.configTextStyle({bold: {expand: "after"}});
|
|
2583
|
+
* const text = doc.getText("text");
|
|
2584
|
+
* text.insert(0, "Hello World!");
|
|
2585
|
+
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
2586
|
+
* ```
|
|
2587
|
+
* @param {{ start: number, end: number }} range
|
|
2588
|
+
* @param {string} key
|
|
2589
|
+
* @param {any} value
|
|
2590
|
+
*/
|
|
2591
|
+
mark(range: { start: number, end: number }, key: string, value: any): void;
|
|
2592
|
+
/**
|
|
2593
|
+
* Unmark a range of text with a key and a value (utf-16 index).
|
|
2594
|
+
*
|
|
2595
|
+
* > You should call `configTextStyle` before using `mark` and `unmark`.
|
|
2596
|
+
*
|
|
2597
|
+
* You can use it to remove highlights, bolds or links
|
|
2598
|
+
*
|
|
2599
|
+
* @example
|
|
2600
|
+
* ```ts
|
|
2601
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2602
|
+
*
|
|
2603
|
+
* const doc = new LoroDoc();
|
|
2604
|
+
* doc.configTextStyle({bold: {expand: "after"}});
|
|
2605
|
+
* const text = doc.getText("text");
|
|
2606
|
+
* text.insert(0, "Hello World!");
|
|
2607
|
+
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
2608
|
+
* text.unmark({ start: 0, end: 5 }, "bold");
|
|
2609
|
+
* ```
|
|
2610
|
+
* @param {{ start: number, end: number }} range
|
|
2611
|
+
* @param {string} key
|
|
2612
|
+
*/
|
|
2613
|
+
unmark(range: { start: number, end: number }, key: string): void;
|
|
2614
|
+
/**
|
|
2615
|
+
* Convert the text to a string
|
|
2616
|
+
* @returns {string}
|
|
2617
|
+
*/
|
|
2618
|
+
toString(): string;
|
|
2619
|
+
/**
|
|
2620
|
+
* Get the text in [Delta](https://quilljs.com/docs/delta/) format.
|
|
2621
|
+
*
|
|
2622
|
+
* The returned value will include the rich text information.
|
|
2623
|
+
*
|
|
2624
|
+
* @example
|
|
2625
|
+
* ```ts
|
|
2626
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2627
|
+
*
|
|
2628
|
+
* const doc = new LoroDoc();
|
|
2629
|
+
* const text = doc.getText("text");
|
|
2630
|
+
* doc.configTextStyle({bold: {expand: "after"}});
|
|
2631
|
+
* text.insert(0, "Hello World!");
|
|
2632
|
+
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
2633
|
+
* console.log(text.toDelta()); // [ { insert: 'Hello', attributes: { bold: true } } ]
|
|
2634
|
+
* ```
|
|
2635
|
+
* @returns {Delta<string>[]}
|
|
2636
|
+
*/
|
|
2637
|
+
toDelta(): Delta<string>[];
|
|
2638
|
+
/**
|
|
2639
|
+
* Change the state of this text by delta.
|
|
2640
|
+
*
|
|
2641
|
+
* If a delta item is `insert`, it should include all the attributes of the inserted text.
|
|
2642
|
+
* Loro's rich text CRDT may make the inserted text inherit some styles when you use
|
|
2643
|
+
* `insert` method directly. However, when you use `applyDelta` if some attributes are
|
|
2644
|
+
* inherited from CRDT but not included in the delta, they will be removed.
|
|
2645
|
+
*
|
|
2646
|
+
* Another special property of `applyDelta` is if you format an attribute for ranges out of
|
|
2647
|
+
* the text length, Loro will insert new lines to fill the gap first. It's useful when you
|
|
2648
|
+
* build the binding between Loro and rich text editors like Quill, which might assume there
|
|
2649
|
+
* is always a newline at the end of the text implicitly.
|
|
2650
|
+
*
|
|
2651
|
+
* @example
|
|
2652
|
+
* ```ts
|
|
2653
|
+
* const doc = new LoroDoc();
|
|
2654
|
+
* const text = doc.getText("text");
|
|
2655
|
+
* doc.configTextStyle({bold: {expand: "after"}});
|
|
2656
|
+
* text.insert(0, "Hello World!");
|
|
2657
|
+
* text.mark({ start: 0, end: 5 }, "bold", true);
|
|
2658
|
+
* const delta = text.toDelta();
|
|
2659
|
+
* const text2 = doc.getText("text2");
|
|
2660
|
+
* text2.applyDelta(delta);
|
|
2661
|
+
* expect(text2.toDelta()).toStrictEqual(delta);
|
|
2662
|
+
* ```
|
|
2663
|
+
* @param {Delta<string>[]} delta
|
|
2664
|
+
*/
|
|
2665
|
+
applyDelta(delta: Delta<string>[]): void;
|
|
2666
|
+
/**
|
|
2667
|
+
* Get the parent container.
|
|
2668
|
+
*
|
|
2669
|
+
* - The parent of the root is `undefined`.
|
|
2670
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2671
|
+
* the WASM boundary.
|
|
2672
|
+
* @returns {Container | undefined}
|
|
2673
|
+
*/
|
|
2674
|
+
parent(): Container | undefined;
|
|
2675
|
+
/**
|
|
2676
|
+
* Whether the container is attached to a LoroDoc.
|
|
2677
|
+
*
|
|
2678
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
2679
|
+
* @returns {boolean}
|
|
2680
|
+
*/
|
|
2681
|
+
isAttached(): boolean;
|
|
2682
|
+
/**
|
|
2683
|
+
* Get the attached container associated with this.
|
|
2684
|
+
*
|
|
2685
|
+
* Returns an attached `Container` that is equal to this or created by this; otherwise, it returns `undefined`.
|
|
2686
|
+
* @returns {LoroText | undefined}
|
|
2687
|
+
*/
|
|
2688
|
+
getAttached(): LoroText | undefined;
|
|
2689
|
+
/**
|
|
2690
|
+
* Get the container id of the text.
|
|
2691
|
+
*/
|
|
2692
|
+
readonly id: ContainerID;
|
|
2693
|
+
/**
|
|
2694
|
+
* Get the length of text (utf-16 length).
|
|
2695
|
+
*/
|
|
2696
|
+
readonly length: number;
|
|
2697
|
+
}
|
|
2698
|
+
/**
|
|
2699
|
+
* The handler of a tree(forest) container.
|
|
2700
|
+
*
|
|
2701
|
+
* Learn more at https://loro.dev/docs/tutorial/tree
|
|
2702
|
+
*/
|
|
2703
|
+
export class LoroTree {
|
|
2704
|
+
free(): void;
|
|
2705
|
+
/**
|
|
2706
|
+
* Create a new detached LoroTree (not attached to any LoroDoc).
|
|
2707
|
+
*
|
|
2708
|
+
* The edits on a detached container will not be persisted.
|
|
2709
|
+
* To attach the container to the document, please insert it into an attached container.
|
|
2710
|
+
*/
|
|
2711
|
+
constructor();
|
|
2712
|
+
/**
|
|
2713
|
+
* "Tree"
|
|
2714
|
+
* @returns {'Tree'}
|
|
2715
|
+
*/
|
|
2716
|
+
kind(): 'Tree';
|
|
2717
|
+
/**
|
|
2718
|
+
* Move the target tree node to be a child of the parent.
|
|
2719
|
+
* It's not allowed that the target is an ancestor of the parent
|
|
2720
|
+
* or the target and the parent are the same node.
|
|
2721
|
+
*
|
|
2722
|
+
* @example
|
|
2723
|
+
* ```ts
|
|
2724
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2725
|
+
*
|
|
2726
|
+
* const doc = new LoroDoc();
|
|
2727
|
+
* const tree = doc.getTree("tree");
|
|
2728
|
+
* const root = tree.createNode();
|
|
2729
|
+
* const node = root.createNode();
|
|
2730
|
+
* const node2 = node.createNode();
|
|
2731
|
+
* tree.move(node2.id, root.id);
|
|
2732
|
+
* // Error will be thrown if move operation creates a cycle
|
|
2733
|
+
* // tree.move(root.id, node.id);
|
|
2734
|
+
* ```
|
|
2735
|
+
* @param {TreeID} target
|
|
2736
|
+
* @param {TreeID | undefined} parent
|
|
2737
|
+
* @param {number | undefined} [index]
|
|
2738
|
+
*/
|
|
2739
|
+
move(target: TreeID, parent: TreeID | undefined, index?: number): void;
|
|
2740
|
+
/**
|
|
2741
|
+
* Delete a tree node from the forest.
|
|
2742
|
+
*
|
|
2743
|
+
* @example
|
|
2744
|
+
* ```ts
|
|
2745
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2746
|
+
*
|
|
2747
|
+
* const doc = new LoroDoc();
|
|
2748
|
+
* const tree = doc.getTree("tree");
|
|
2749
|
+
* const root = tree.createNode();
|
|
2750
|
+
* const node = root.createNode();
|
|
2751
|
+
* tree.delete(node.id);
|
|
2752
|
+
* ```
|
|
2753
|
+
* @param {TreeID} target
|
|
2754
|
+
*/
|
|
2755
|
+
delete(target: TreeID): void;
|
|
2756
|
+
/**
|
|
2757
|
+
* Return `true` if the tree contains the TreeID, include deleted node.
|
|
2758
|
+
* @param {TreeID} target
|
|
2759
|
+
* @returns {boolean}
|
|
2760
|
+
*/
|
|
2761
|
+
has(target: TreeID): boolean;
|
|
2762
|
+
/**
|
|
2763
|
+
* Return `None` if the node is not exist, otherwise return `Some(true)` if the node is deleted.
|
|
2764
|
+
* @param {TreeID} target
|
|
2765
|
+
* @returns {boolean}
|
|
2766
|
+
*/
|
|
2767
|
+
isNodeDeleted(target: TreeID): boolean;
|
|
2768
|
+
/**
|
|
2769
|
+
* Get the hierarchy array with metadata of the forest.
|
|
2770
|
+
*
|
|
2771
|
+
* @example
|
|
2772
|
+
* ```ts
|
|
2773
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2774
|
+
*
|
|
2775
|
+
* const doc = new LoroDoc();
|
|
2776
|
+
* const tree = doc.getTree("tree");
|
|
2777
|
+
* const root = tree.createNode();
|
|
2778
|
+
* root.data.set("color", "red");
|
|
2779
|
+
* // [ { id: '0@F2462C4159C4C8D1', parent: null, meta: { color: 'red' }, children: [] } ]
|
|
2780
|
+
* console.log(tree.toJSON());
|
|
2781
|
+
* ```
|
|
2782
|
+
* @returns {any}
|
|
2783
|
+
*/
|
|
2784
|
+
toJSON(): any;
|
|
2785
|
+
/**
|
|
2786
|
+
* Get all tree nodes of the forest, including deleted nodes.
|
|
2787
|
+
*
|
|
2788
|
+
* @example
|
|
2789
|
+
* ```ts
|
|
2790
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2791
|
+
*
|
|
2792
|
+
* const doc = new LoroDoc();
|
|
2793
|
+
* const tree = doc.getTree("tree");
|
|
2794
|
+
* const root = tree.createNode();
|
|
2795
|
+
* const node = root.createNode();
|
|
2796
|
+
* const node2 = node.createNode();
|
|
2797
|
+
* console.log(tree.nodes());
|
|
2798
|
+
* ```
|
|
2799
|
+
* @returns {(LoroTreeNode)[]}
|
|
2800
|
+
*/
|
|
2801
|
+
nodes(): (LoroTreeNode)[];
|
|
2802
|
+
/**
|
|
2803
|
+
* Get the root nodes of the forest.
|
|
2804
|
+
* @returns {(LoroTreeNode)[]}
|
|
2805
|
+
*/
|
|
2806
|
+
roots(): (LoroTreeNode)[];
|
|
2807
|
+
/**
|
|
2808
|
+
* Get the parent container of the tree container.
|
|
2809
|
+
*
|
|
2810
|
+
* - The parent container of the root tree is `undefined`.
|
|
2811
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2812
|
+
* the WASM boundary.
|
|
2813
|
+
* @returns {Container | undefined}
|
|
2814
|
+
*/
|
|
2815
|
+
parent(): Container | undefined;
|
|
2816
|
+
/**
|
|
2817
|
+
* Whether the container is attached to a document.
|
|
2818
|
+
*
|
|
2819
|
+
* If it's detached, the operations on the container will not be persisted.
|
|
2820
|
+
* @returns {boolean}
|
|
2821
|
+
*/
|
|
2822
|
+
isAttached(): boolean;
|
|
2823
|
+
/**
|
|
2824
|
+
* Get the attached container associated with this.
|
|
2825
|
+
*
|
|
2826
|
+
* Returns an attached `Container` that equals to this or created by this, otherwise `undefined`.
|
|
2827
|
+
* @returns {LoroTree | undefined}
|
|
2828
|
+
*/
|
|
2829
|
+
getAttached(): LoroTree | undefined;
|
|
2830
|
+
/**
|
|
2831
|
+
* Set whether to generate a fractional index for moving and creating.
|
|
2832
|
+
*
|
|
2833
|
+
* A fractional index can be used to determine the position of tree nodes among their siblings.
|
|
2834
|
+
*
|
|
2835
|
+
* The jitter is used to avoid conflicts when multiple users are creating a node at the same position.
|
|
2836
|
+
* A value of 0 is the default, which means no jitter; any value larger than 0 will enable jitter.
|
|
2837
|
+
*
|
|
2838
|
+
* Generally speaking, higher jitter value will increase the size of the operation
|
|
2839
|
+
* [Read more about it](https://www.loro.dev/blog/movable-tree#implementation-and-encoding-size)
|
|
2840
|
+
* @param {number} jitter
|
|
2841
|
+
*/
|
|
2842
|
+
enableFractionalIndex(jitter: number): void;
|
|
2843
|
+
/**
|
|
2844
|
+
* Disable the fractional index generation for Tree Position when
|
|
2845
|
+
* you don't need the Tree's siblings to be sorted. The fractional index will always be set to default.
|
|
2846
|
+
*/
|
|
2847
|
+
disableFractionalIndex(): void;
|
|
2848
|
+
/**
|
|
2849
|
+
* Whether the tree enables the fractional index generation.
|
|
2850
|
+
* @returns {boolean}
|
|
2851
|
+
*/
|
|
2852
|
+
isFractionalIndexEnabled(): boolean;
|
|
2853
|
+
/**
|
|
2854
|
+
* Get the id of the container.
|
|
2855
|
+
*/
|
|
2856
|
+
readonly id: ContainerID;
|
|
2857
|
+
}
|
|
2858
|
+
/**
|
|
2859
|
+
* The handler of a tree node.
|
|
2860
|
+
*/
|
|
2861
|
+
export class LoroTreeNode {
|
|
2862
|
+
free(): void;
|
|
2863
|
+
/**
|
|
2864
|
+
* @returns {string}
|
|
2865
|
+
*/
|
|
2866
|
+
__getClassname(): string;
|
|
2867
|
+
/**
|
|
2868
|
+
* Move this tree node to be a child of the parent.
|
|
2869
|
+
* If the parent is undefined, this node will be a root node.
|
|
2870
|
+
*
|
|
2871
|
+
* If the index is not provided, the node will be appended to the end.
|
|
2872
|
+
*
|
|
2873
|
+
* It's not allowed that the target is an ancestor of the parent.
|
|
2874
|
+
*
|
|
2875
|
+
* @example
|
|
2876
|
+
* ```ts
|
|
2877
|
+
* const doc = new LoroDoc();
|
|
2878
|
+
* const tree = doc.getTree("tree");
|
|
2879
|
+
* const root = tree.createNode();
|
|
2880
|
+
* const node = root.createNode();
|
|
2881
|
+
* const node2 = node.createNode();
|
|
2882
|
+
* node2.move(undefined, 0);
|
|
2883
|
+
* // node2 root
|
|
2884
|
+
* // |
|
|
2885
|
+
* // node
|
|
2886
|
+
*
|
|
2887
|
+
* ```
|
|
2888
|
+
* @param {LoroTreeNode | undefined} parent
|
|
2889
|
+
* @param {number | undefined} [index]
|
|
2890
|
+
*/
|
|
2891
|
+
move(parent: LoroTreeNode | undefined, index?: number): void;
|
|
2892
|
+
/**
|
|
2893
|
+
* Move the tree node to be after the target node.
|
|
2894
|
+
*
|
|
2895
|
+
* @example
|
|
2896
|
+
* ```ts
|
|
2897
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2898
|
+
*
|
|
2899
|
+
* const doc = new LoroDoc();
|
|
2900
|
+
* const tree = doc.getTree("tree");
|
|
2901
|
+
* const root = tree.createNode();
|
|
2902
|
+
* const node = root.createNode();
|
|
2903
|
+
* const node2 = root.createNode();
|
|
2904
|
+
* node2.moveAfter(node);
|
|
2905
|
+
* // root
|
|
2906
|
+
* // / \
|
|
2907
|
+
* // node node2
|
|
2908
|
+
* ```
|
|
2909
|
+
* @param {LoroTreeNode} target
|
|
2910
|
+
*/
|
|
2911
|
+
moveAfter(target: LoroTreeNode): void;
|
|
2912
|
+
/**
|
|
2913
|
+
* Move the tree node to be before the target node.
|
|
2914
|
+
*
|
|
2915
|
+
* @example
|
|
2916
|
+
* ```ts
|
|
2917
|
+
* import { LoroDoc } from "loro-crdt";
|
|
2918
|
+
*
|
|
2919
|
+
* const doc = new LoroDoc();
|
|
2920
|
+
* const tree = doc.getTree("tree");
|
|
2921
|
+
* const root = tree.createNode();
|
|
2922
|
+
* const node = root.createNode();
|
|
2923
|
+
* const node2 = root.createNode();
|
|
2924
|
+
* node2.moveBefore(node);
|
|
2925
|
+
* // root
|
|
2926
|
+
* // / \
|
|
2927
|
+
* // node2 node
|
|
2928
|
+
* ```
|
|
2929
|
+
* @param {LoroTreeNode} target
|
|
2930
|
+
*/
|
|
2931
|
+
moveBefore(target: LoroTreeNode): void;
|
|
2932
|
+
/**
|
|
2933
|
+
* Get the index of the node in the parent's children.
|
|
2934
|
+
* @returns {number | undefined}
|
|
2935
|
+
*/
|
|
2936
|
+
index(): number | undefined;
|
|
2937
|
+
/**
|
|
2938
|
+
* Get the `Fractional Index` of the node.
|
|
2939
|
+
*
|
|
2940
|
+
* Note: the tree container must be attached to the document.
|
|
2941
|
+
* @returns {string | undefined}
|
|
2942
|
+
*/
|
|
2943
|
+
fractionalIndex(): string | undefined;
|
|
2944
|
+
/**
|
|
2945
|
+
* Get the parent node of this node.
|
|
2946
|
+
*
|
|
2947
|
+
* - The parent of the root node is `undefined`.
|
|
2948
|
+
* - The object returned is a new js object each time because it need to cross
|
|
2949
|
+
* the WASM boundary.
|
|
2950
|
+
* @returns {LoroTreeNode | undefined}
|
|
2951
|
+
*/
|
|
2952
|
+
parent(): LoroTreeNode | undefined;
|
|
2953
|
+
/**
|
|
2954
|
+
* Check if the node is deleted.
|
|
2955
|
+
* @returns {boolean}
|
|
2956
|
+
*/
|
|
2957
|
+
isDeleted(): boolean;
|
|
2958
|
+
/**
|
|
2959
|
+
* The TreeID of the node.
|
|
2960
|
+
*/
|
|
2961
|
+
readonly id: TreeID;
|
|
2962
|
+
}
|
|
2963
|
+
/**
|
|
2964
|
+
* `UndoManager` is responsible for handling undo and redo operations.
|
|
2965
|
+
*
|
|
2966
|
+
* By default, the maxUndoSteps is set to 100, mergeInterval is set to 1000 ms.
|
|
2967
|
+
*
|
|
2968
|
+
* Each commit made by the current peer is recorded as an undo step in the `UndoManager`.
|
|
2969
|
+
* Undo steps can be merged if they occur within a specified merge interval.
|
|
2970
|
+
*
|
|
2971
|
+
* Note that undo operations are local and cannot revert changes made by other peers.
|
|
2972
|
+
* To undo changes made by other peers, consider using the time travel feature.
|
|
2973
|
+
*
|
|
2974
|
+
* Once the `peerId` is bound to the `UndoManager` in the document, it cannot be changed.
|
|
2975
|
+
* Otherwise, the `UndoManager` may not function correctly.
|
|
2976
|
+
*/
|
|
2977
|
+
export class UndoManager {
|
|
2978
|
+
free(): void;
|
|
2979
|
+
/**
|
|
2980
|
+
* `UndoManager` is responsible for handling undo and redo operations.
|
|
2981
|
+
*
|
|
2982
|
+
* PeerID cannot be changed during the lifetime of the UndoManager.
|
|
2983
|
+
*
|
|
2984
|
+
* Note that undo operations are local and cannot revert changes made by other peers.
|
|
2985
|
+
* To undo changes made by other peers, consider using the time travel feature.
|
|
2986
|
+
*
|
|
2987
|
+
* Each commit made by the current peer is recorded as an undo step in the `UndoManager`.
|
|
2988
|
+
* Undo steps can be merged if they occur within a specified merge interval.
|
|
2989
|
+
*
|
|
2990
|
+
* ## Config
|
|
2991
|
+
*
|
|
2992
|
+
* - `mergeInterval`: Optional. The interval in milliseconds within which undo steps can be merged. Default is 1000 ms.
|
|
2993
|
+
* - `maxUndoSteps`: Optional. The maximum number of undo steps to retain. Default is 100.
|
|
2994
|
+
* - `excludeOriginPrefixes`: Optional. An array of string prefixes. Events with origins matching these prefixes will be excluded from undo steps.
|
|
2995
|
+
* - `onPush`: Optional. A callback function that is called when an undo/redo step is pushed.
|
|
2996
|
+
* The function can return a meta data value that will be attached to the given stack item.
|
|
2997
|
+
* - `onPop`: Optional. A callback function that is called when an undo/redo step is popped.
|
|
2998
|
+
* The function will have a meta data value that was attached to the given stack item when
|
|
2999
|
+
* `onPush` was called.
|
|
3000
|
+
* @param {LoroDoc} doc
|
|
3001
|
+
* @param {UndoConfig} config
|
|
3002
|
+
*/
|
|
3003
|
+
constructor(doc: LoroDoc, config: UndoConfig);
|
|
3004
|
+
/**
|
|
3005
|
+
* Undo the last operation.
|
|
3006
|
+
* @returns {boolean}
|
|
3007
|
+
*/
|
|
3008
|
+
undo(): boolean;
|
|
3009
|
+
/**
|
|
3010
|
+
* Redo the last undone operation.
|
|
3011
|
+
* @returns {boolean}
|
|
3012
|
+
*/
|
|
3013
|
+
redo(): boolean;
|
|
3014
|
+
/**
|
|
3015
|
+
* Can undo the last operation.
|
|
3016
|
+
* @returns {boolean}
|
|
3017
|
+
*/
|
|
3018
|
+
canUndo(): boolean;
|
|
3019
|
+
/**
|
|
3020
|
+
* Can redo the last operation.
|
|
3021
|
+
* @returns {boolean}
|
|
3022
|
+
*/
|
|
3023
|
+
canRedo(): boolean;
|
|
3024
|
+
/**
|
|
3025
|
+
* The number of max undo steps.
|
|
3026
|
+
* If the number of undo steps exceeds this number, the oldest undo step will be removed.
|
|
3027
|
+
* @param {number} steps
|
|
3028
|
+
*/
|
|
3029
|
+
setMaxUndoSteps(steps: number): void;
|
|
3030
|
+
/**
|
|
3031
|
+
* Set the merge interval (in ms).
|
|
3032
|
+
* If the interval is set to 0, the undo steps will not be merged.
|
|
3033
|
+
* Otherwise, the undo steps will be merged if the interval between the two steps is less than the given interval.
|
|
3034
|
+
* @param {number} interval
|
|
3035
|
+
*/
|
|
3036
|
+
setMergeInterval(interval: number): void;
|
|
3037
|
+
/**
|
|
3038
|
+
* If a local event's origin matches the given prefix, it will not be recorded in the
|
|
3039
|
+
* undo stack.
|
|
3040
|
+
* @param {string} prefix
|
|
3041
|
+
*/
|
|
3042
|
+
addExcludeOriginPrefix(prefix: string): void;
|
|
3043
|
+
/**
|
|
3044
|
+
* Check if the undo manager is bound to the given document.
|
|
3045
|
+
* @param {LoroDoc} doc
|
|
3046
|
+
* @returns {boolean}
|
|
3047
|
+
*/
|
|
3048
|
+
checkBinding(doc: LoroDoc): boolean;
|
|
3049
|
+
/**
|
|
3050
|
+
*/
|
|
3051
|
+
clear(): void;
|
|
3052
|
+
}
|
|
3053
|
+
/**
|
|
3054
|
+
* [VersionVector](https://en.wikipedia.org/wiki/Version_vector)
|
|
3055
|
+
* is a map from [PeerID] to [Counter]. Its a right-open interval.
|
|
3056
|
+
*
|
|
3057
|
+
* i.e. a [VersionVector] of `{A: 1, B: 2}` means that A has 1 atomic op and B has 2 atomic ops,
|
|
3058
|
+
* thus ID of `{client: A, counter: 1}` is out of the range.
|
|
3059
|
+
*/
|
|
3060
|
+
export class VersionVector {
|
|
3061
|
+
free(): void;
|
|
3062
|
+
/**
|
|
3063
|
+
* Create a new version vector.
|
|
3064
|
+
* @param {Map<PeerID, number> | Uint8Array | VersionVector | undefined | null} value
|
|
3065
|
+
*/
|
|
3066
|
+
constructor(value: Map<PeerID, number> | Uint8Array | VersionVector | undefined | null);
|
|
3067
|
+
/**
|
|
3068
|
+
* Create a new version vector from a Map.
|
|
3069
|
+
* @param {Map<PeerID, number>} version
|
|
3070
|
+
* @returns {VersionVector}
|
|
3071
|
+
*/
|
|
3072
|
+
static parseJSON(version: Map<PeerID, number>): VersionVector;
|
|
3073
|
+
/**
|
|
3074
|
+
* Convert the version vector to a Map
|
|
3075
|
+
* @returns {Map<PeerID, number>}
|
|
3076
|
+
*/
|
|
3077
|
+
toJSON(): Map<PeerID, number>;
|
|
3078
|
+
/**
|
|
3079
|
+
* Encode the version vector into a Uint8Array.
|
|
3080
|
+
* @returns {Uint8Array}
|
|
3081
|
+
*/
|
|
3082
|
+
encode(): Uint8Array;
|
|
3083
|
+
/**
|
|
3084
|
+
* Decode the version vector from a Uint8Array.
|
|
3085
|
+
* @param {Uint8Array} bytes
|
|
3086
|
+
* @returns {VersionVector}
|
|
3087
|
+
*/
|
|
3088
|
+
static decode(bytes: Uint8Array): VersionVector;
|
|
3089
|
+
/**
|
|
3090
|
+
* Get the counter of a peer.
|
|
3091
|
+
* @param {number | bigint | `${number}`} peer_id
|
|
3092
|
+
* @returns {number | undefined}
|
|
3093
|
+
*/
|
|
3094
|
+
get(peer_id: number | bigint | `${number}`): number | undefined;
|
|
3095
|
+
/**
|
|
3096
|
+
* Compare the version vector with another version vector.
|
|
3097
|
+
*
|
|
3098
|
+
* If they are concurrent, return undefined.
|
|
3099
|
+
* @param {VersionVector} other
|
|
3100
|
+
* @returns {number | undefined}
|
|
3101
|
+
*/
|
|
3102
|
+
compare(other: VersionVector): number | undefined;
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
3106
|
+
|
|
3107
|
+
export interface InitOutput {
|
|
3108
|
+
readonly memory: WebAssembly.Memory;
|
|
3109
|
+
readonly __wbg_lorocounter_free: (a: number) => void;
|
|
3110
|
+
readonly lorocounter_new: () => number;
|
|
3111
|
+
readonly lorocounter_increment: (a: number, b: number, c: number) => void;
|
|
3112
|
+
readonly lorocounter_decrement: (a: number, b: number, c: number) => void;
|
|
3113
|
+
readonly lorocounter_value: (a: number) => number;
|
|
3114
|
+
readonly lorocounter_subscribe: (a: number, b: number, c: number) => void;
|
|
3115
|
+
readonly lorocounter_parent: (a: number) => number;
|
|
3116
|
+
readonly lorocounter_isAttached: (a: number) => number;
|
|
3117
|
+
readonly lorocounter_getAttached: (a: number) => number;
|
|
3118
|
+
readonly __wbg_awarenesswasm_free: (a: number) => void;
|
|
3119
|
+
readonly awarenesswasm_new: (a: number, b: number) => number;
|
|
3120
|
+
readonly awarenesswasm_encode: (a: number, b: number, c: number) => void;
|
|
3121
|
+
readonly awarenesswasm_encodeAll: (a: number, b: number) => void;
|
|
3122
|
+
readonly awarenesswasm_apply: (a: number, b: number, c: number, d: number) => void;
|
|
3123
|
+
readonly awarenesswasm_setLocalState: (a: number, b: number) => void;
|
|
3124
|
+
readonly awarenesswasm_peer: (a: number) => number;
|
|
3125
|
+
readonly awarenesswasm_getAllStates: (a: number) => number;
|
|
3126
|
+
readonly awarenesswasm_getState: (a: number, b: number) => number;
|
|
3127
|
+
readonly awarenesswasm_getTimestamp: (a: number, b: number, c: number) => void;
|
|
3128
|
+
readonly awarenesswasm_removeOutdated: (a: number, b: number) => void;
|
|
3129
|
+
readonly awarenesswasm_length: (a: number) => number;
|
|
3130
|
+
readonly awarenesswasm_isEmpty: (a: number) => number;
|
|
3131
|
+
readonly awarenesswasm_peers: (a: number, b: number) => void;
|
|
3132
|
+
readonly run: () => void;
|
|
3133
|
+
readonly encodeFrontiers: (a: number, b: number, c: number) => void;
|
|
3134
|
+
readonly decodeFrontiers: (a: number, b: number, c: number) => void;
|
|
3135
|
+
readonly setDebug: () => void;
|
|
3136
|
+
readonly __wbg_lorodoc_free: (a: number) => void;
|
|
3137
|
+
readonly lorodoc_new: () => number;
|
|
3138
|
+
readonly lorodoc_setDetachedEditing: (a: number, b: number) => void;
|
|
3139
|
+
readonly lorodoc_isDetachedEditingEnabled: (a: number) => number;
|
|
3140
|
+
readonly lorodoc_setRecordTimestamp: (a: number, b: number) => void;
|
|
3141
|
+
readonly lorodoc_setChangeMergeInterval: (a: number, b: number) => void;
|
|
3142
|
+
readonly lorodoc_configTextStyle: (a: number, b: number, c: number) => void;
|
|
3143
|
+
readonly lorodoc_fromSnapshot: (a: number, b: number, c: number) => void;
|
|
3144
|
+
readonly lorodoc_attach: (a: number) => void;
|
|
3145
|
+
readonly lorodoc_isDetached: (a: number) => number;
|
|
3146
|
+
readonly lorodoc_detach: (a: number) => void;
|
|
3147
|
+
readonly lorodoc_fork: (a: number) => number;
|
|
3148
|
+
readonly lorodoc_forkAt: (a: number, b: number, c: number, d: number) => void;
|
|
3149
|
+
readonly lorodoc_checkoutToLatest: (a: number, b: number) => void;
|
|
3150
|
+
readonly lorodoc_travelChangeAncestors: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3151
|
+
readonly lorodoc_checkout: (a: number, b: number, c: number, d: number) => void;
|
|
3152
|
+
readonly lorodoc_peerId: (a: number) => number;
|
|
3153
|
+
readonly lorodoc_peerIdStr: (a: number) => number;
|
|
3154
|
+
readonly lorodoc_setPeerId: (a: number, b: number, c: number) => void;
|
|
3155
|
+
readonly lorodoc_commit: (a: number, b: number, c: number) => void;
|
|
3156
|
+
readonly lorodoc_getPendingTxnLength: (a: number) => number;
|
|
3157
|
+
readonly lorodoc_getText: (a: number, b: number, c: number) => void;
|
|
3158
|
+
readonly lorodoc_getMap: (a: number, b: number, c: number) => void;
|
|
3159
|
+
readonly lorodoc_getList: (a: number, b: number, c: number) => void;
|
|
3160
|
+
readonly lorodoc_getMovableList: (a: number, b: number, c: number) => void;
|
|
3161
|
+
readonly lorodoc_getCounter: (a: number, b: number, c: number) => void;
|
|
3162
|
+
readonly lorodoc_getTree: (a: number, b: number, c: number) => void;
|
|
3163
|
+
readonly lorodoc_getContainerById: (a: number, b: number, c: number) => void;
|
|
3164
|
+
readonly lorodoc_setNextCommitMessage: (a: number, b: number, c: number) => void;
|
|
3165
|
+
readonly lorodoc_getDeepValueWithID: (a: number) => number;
|
|
3166
|
+
readonly lorodoc_getPathToContainer: (a: number, b: number, c: number) => void;
|
|
3167
|
+
readonly lorodoc_JSONPath: (a: number, b: number, c: number, d: number) => void;
|
|
3168
|
+
readonly lorodoc_version: (a: number) => number;
|
|
3169
|
+
readonly lorodoc_shallowSinceVV: (a: number) => number;
|
|
3170
|
+
readonly lorodoc_isShallow: (a: number) => number;
|
|
3171
|
+
readonly lorodoc_shallowSinceFrontiers: (a: number) => number;
|
|
3172
|
+
readonly lorodoc_oplogVersion: (a: number) => number;
|
|
3173
|
+
readonly lorodoc_frontiers: (a: number) => number;
|
|
3174
|
+
readonly lorodoc_oplogFrontiers: (a: number) => number;
|
|
3175
|
+
readonly lorodoc_cmpWithFrontiers: (a: number, b: number, c: number, d: number) => void;
|
|
3176
|
+
readonly lorodoc_cmpFrontiers: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
3177
|
+
readonly lorodoc_exportSnapshot: (a: number, b: number) => void;
|
|
3178
|
+
readonly lorodoc_exportFrom: (a: number, b: number, c: number) => void;
|
|
3179
|
+
readonly lorodoc_export: (a: number, b: number, c: number) => void;
|
|
3180
|
+
readonly lorodoc_exportJsonUpdates: (a: number, b: number, c: number, d: number) => void;
|
|
3181
|
+
readonly lorodoc_importJsonUpdates: (a: number, b: number, c: number) => void;
|
|
3182
|
+
readonly lorodoc_import: (a: number, b: number, c: number, d: number) => void;
|
|
3183
|
+
readonly lorodoc_importUpdateBatch: (a: number, b: number, c: number) => void;
|
|
3184
|
+
readonly lorodoc_getShallowValue: (a: number, b: number) => void;
|
|
3185
|
+
readonly lorodoc_toJSON: (a: number, b: number) => void;
|
|
3186
|
+
readonly lorodoc_subscribe: (a: number, b: number) => number;
|
|
3187
|
+
readonly lorodoc_subscribeLocalUpdates: (a: number, b: number) => number;
|
|
3188
|
+
readonly lorodoc_debugHistory: (a: number) => void;
|
|
3189
|
+
readonly lorodoc_getAllChanges: (a: number) => number;
|
|
3190
|
+
readonly lorodoc_getChangeAt: (a: number, b: number, c: number) => void;
|
|
3191
|
+
readonly lorodoc_getChangeAtLamport: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3192
|
+
readonly lorodoc_getOpsInChange: (a: number, b: number, c: number) => void;
|
|
3193
|
+
readonly lorodoc_frontiersToVV: (a: number, b: number, c: number, d: number) => void;
|
|
3194
|
+
readonly lorodoc_vvToFrontiers: (a: number, b: number, c: number) => void;
|
|
3195
|
+
readonly lorodoc_getByPath: (a: number, b: number, c: number) => number;
|
|
3196
|
+
readonly lorodoc_getCursorPos: (a: number, b: number, c: number) => void;
|
|
3197
|
+
readonly __wbg_lorotext_free: (a: number) => void;
|
|
3198
|
+
readonly lorotext_new: () => number;
|
|
3199
|
+
readonly lorotext_kind: (a: number) => number;
|
|
3200
|
+
readonly lorotext_iter: (a: number, b: number) => void;
|
|
3201
|
+
readonly lorotext_update: (a: number, b: number, c: number) => void;
|
|
3202
|
+
readonly lorotext_updateByLine: (a: number, b: number, c: number) => void;
|
|
3203
|
+
readonly lorotext_insert: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3204
|
+
readonly lorotext_slice: (a: number, b: number, c: number, d: number) => void;
|
|
3205
|
+
readonly lorotext_charAt: (a: number, b: number, c: number) => void;
|
|
3206
|
+
readonly lorotext_splice: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
3207
|
+
readonly lorotext_insertUtf8: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3208
|
+
readonly lorotext_delete: (a: number, b: number, c: number, d: number) => void;
|
|
3209
|
+
readonly lorotext_deleteUtf8: (a: number, b: number, c: number, d: number) => void;
|
|
3210
|
+
readonly lorotext_mark: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
3211
|
+
readonly lorotext_unmark: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3212
|
+
readonly lorotext_toString: (a: number, b: number) => void;
|
|
3213
|
+
readonly lorotext_toDelta: (a: number) => number;
|
|
3214
|
+
readonly lorotext_id: (a: number) => number;
|
|
3215
|
+
readonly lorotext_length: (a: number) => number;
|
|
3216
|
+
readonly lorotext_subscribe: (a: number, b: number, c: number) => void;
|
|
3217
|
+
readonly lorotext_applyDelta: (a: number, b: number, c: number) => void;
|
|
3218
|
+
readonly lorotext_parent: (a: number) => number;
|
|
3219
|
+
readonly lorotext_getAttached: (a: number) => number;
|
|
3220
|
+
readonly lorotext_getCursor: (a: number, b: number, c: number) => number;
|
|
3221
|
+
readonly __wbg_loromap_free: (a: number) => void;
|
|
3222
|
+
readonly loromap_new: () => number;
|
|
3223
|
+
readonly loromap_kind: (a: number) => number;
|
|
3224
|
+
readonly loromap_set: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3225
|
+
readonly loromap_delete: (a: number, b: number, c: number, d: number) => void;
|
|
3226
|
+
readonly loromap_get: (a: number, b: number, c: number) => number;
|
|
3227
|
+
readonly loromap_getOrCreateContainer: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3228
|
+
readonly loromap_keys: (a: number, b: number) => void;
|
|
3229
|
+
readonly loromap_values: (a: number, b: number) => void;
|
|
3230
|
+
readonly loromap_entries: (a: number, b: number) => void;
|
|
3231
|
+
readonly loromap_id: (a: number) => number;
|
|
3232
|
+
readonly loromap_toJSON: (a: number) => number;
|
|
3233
|
+
readonly loromap_setContainer: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3234
|
+
readonly loromap_subscribe: (a: number, b: number, c: number) => void;
|
|
3235
|
+
readonly loromap_size: (a: number) => number;
|
|
3236
|
+
readonly loromap_parent: (a: number) => number;
|
|
3237
|
+
readonly loromap_getAttached: (a: number) => number;
|
|
3238
|
+
readonly loromap_clear: (a: number, b: number) => void;
|
|
3239
|
+
readonly __wbg_lorolist_free: (a: number) => void;
|
|
3240
|
+
readonly lorolist_new: () => number;
|
|
3241
|
+
readonly lorolist_kind: (a: number) => number;
|
|
3242
|
+
readonly lorolist_insert: (a: number, b: number, c: number, d: number) => void;
|
|
3243
|
+
readonly lorolist_delete: (a: number, b: number, c: number, d: number) => void;
|
|
3244
|
+
readonly lorolist_get: (a: number, b: number) => number;
|
|
3245
|
+
readonly lorolist_id: (a: number) => number;
|
|
3246
|
+
readonly lorolist_toArray: (a: number, b: number) => void;
|
|
3247
|
+
readonly lorolist_toJSON: (a: number) => number;
|
|
3248
|
+
readonly lorolist_insertContainer: (a: number, b: number, c: number, d: number) => void;
|
|
3249
|
+
readonly lorolist_subscribe: (a: number, b: number, c: number) => void;
|
|
3250
|
+
readonly lorolist_length: (a: number) => number;
|
|
3251
|
+
readonly lorolist_parent: (a: number) => number;
|
|
3252
|
+
readonly lorolist_isAttached: (a: number) => number;
|
|
3253
|
+
readonly lorolist_getAttached: (a: number) => number;
|
|
3254
|
+
readonly lorolist_getCursor: (a: number, b: number, c: number) => number;
|
|
3255
|
+
readonly lorolist_push: (a: number, b: number, c: number) => void;
|
|
3256
|
+
readonly lorolist_pop: (a: number, b: number) => void;
|
|
3257
|
+
readonly lorolist_clear: (a: number, b: number) => void;
|
|
3258
|
+
readonly loromovablelist_new: () => number;
|
|
3259
|
+
readonly loromovablelist_kind: (a: number) => number;
|
|
3260
|
+
readonly loromovablelist_insert: (a: number, b: number, c: number, d: number) => void;
|
|
3261
|
+
readonly loromovablelist_delete: (a: number, b: number, c: number, d: number) => void;
|
|
3262
|
+
readonly loromovablelist_get: (a: number, b: number) => number;
|
|
3263
|
+
readonly loromovablelist_id: (a: number) => number;
|
|
3264
|
+
readonly loromovablelist_toArray: (a: number, b: number) => void;
|
|
3265
|
+
readonly loromovablelist_toJSON: (a: number) => number;
|
|
3266
|
+
readonly loromovablelist_insertContainer: (a: number, b: number, c: number, d: number) => void;
|
|
3267
|
+
readonly loromovablelist_subscribe: (a: number, b: number, c: number) => void;
|
|
3268
|
+
readonly loromovablelist_length: (a: number) => number;
|
|
3269
|
+
readonly loromovablelist_getAttached: (a: number) => number;
|
|
3270
|
+
readonly loromovablelist_getCursor: (a: number, b: number, c: number) => number;
|
|
3271
|
+
readonly loromovablelist_move: (a: number, b: number, c: number, d: number) => void;
|
|
3272
|
+
readonly loromovablelist_set: (a: number, b: number, c: number, d: number) => void;
|
|
3273
|
+
readonly loromovablelist_setContainer: (a: number, b: number, c: number, d: number) => void;
|
|
3274
|
+
readonly loromovablelist_push: (a: number, b: number, c: number) => void;
|
|
3275
|
+
readonly loromovablelist_pop: (a: number, b: number) => void;
|
|
3276
|
+
readonly loromovablelist_clear: (a: number, b: number) => void;
|
|
3277
|
+
readonly __wbg_lorotree_free: (a: number) => void;
|
|
3278
|
+
readonly lorotreenode___getClassname: (a: number, b: number) => void;
|
|
3279
|
+
readonly __wbg_lorotreenode_free: (a: number) => void;
|
|
3280
|
+
readonly lorotreenode_id: (a: number) => number;
|
|
3281
|
+
readonly lorotreenode_createNode: (a: number, b: number, c: number, d: number) => void;
|
|
3282
|
+
readonly lorotreenode_move: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3283
|
+
readonly lorotreenode_moveAfter: (a: number, b: number, c: number) => void;
|
|
3284
|
+
readonly lorotreenode_moveBefore: (a: number, b: number, c: number) => void;
|
|
3285
|
+
readonly lorotreenode_index: (a: number, b: number) => void;
|
|
3286
|
+
readonly lorotreenode_fractionalIndex: (a: number, b: number) => void;
|
|
3287
|
+
readonly lorotreenode_data: (a: number, b: number) => void;
|
|
3288
|
+
readonly lorotreenode_parent: (a: number, b: number) => void;
|
|
3289
|
+
readonly lorotreenode_children: (a: number) => number;
|
|
3290
|
+
readonly lorotreenode_isDeleted: (a: number, b: number) => void;
|
|
3291
|
+
readonly lorotree_new: () => number;
|
|
3292
|
+
readonly lorotree_kind: (a: number) => number;
|
|
3293
|
+
readonly lorotree_createNode: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
3294
|
+
readonly lorotree_move: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
3295
|
+
readonly lorotree_delete: (a: number, b: number, c: number) => void;
|
|
3296
|
+
readonly lorotree_getNodeByID: (a: number, b: number) => number;
|
|
3297
|
+
readonly lorotree_id: (a: number) => number;
|
|
3298
|
+
readonly lorotree_has: (a: number, b: number) => number;
|
|
3299
|
+
readonly lorotree_isNodeDeleted: (a: number, b: number, c: number) => void;
|
|
3300
|
+
readonly lorotree_toArray: (a: number, b: number) => void;
|
|
3301
|
+
readonly lorotree_getNodes: (a: number, b: number, c: number) => void;
|
|
3302
|
+
readonly lorotree_toJSON: (a: number) => number;
|
|
3303
|
+
readonly lorotree_nodes: (a: number, b: number) => void;
|
|
3304
|
+
readonly lorotree_roots: (a: number, b: number) => void;
|
|
3305
|
+
readonly lorotree_subscribe: (a: number, b: number, c: number) => void;
|
|
3306
|
+
readonly lorotree_parent: (a: number) => number;
|
|
3307
|
+
readonly lorotree_isAttached: (a: number) => number;
|
|
3308
|
+
readonly lorotree_getAttached: (a: number) => number;
|
|
3309
|
+
readonly lorotree_enableFractionalIndex: (a: number, b: number) => void;
|
|
3310
|
+
readonly lorotree_disableFractionalIndex: (a: number) => void;
|
|
3311
|
+
readonly lorotree_isFractionalIndexEnabled: (a: number) => number;
|
|
3312
|
+
readonly __wbg_cursor_free: (a: number) => void;
|
|
3313
|
+
readonly cursor_containerId: (a: number) => number;
|
|
3314
|
+
readonly cursor_pos: (a: number) => number;
|
|
3315
|
+
readonly cursor_side: (a: number) => number;
|
|
3316
|
+
readonly cursor_encode: (a: number, b: number) => void;
|
|
3317
|
+
readonly cursor_decode: (a: number, b: number, c: number) => void;
|
|
3318
|
+
readonly cursor_kind: (a: number) => number;
|
|
3319
|
+
readonly __wbg_undomanager_free: (a: number) => void;
|
|
3320
|
+
readonly undomanager_new: (a: number, b: number) => number;
|
|
3321
|
+
readonly undomanager_undo: (a: number, b: number) => void;
|
|
3322
|
+
readonly undomanager_redo: (a: number, b: number) => void;
|
|
3323
|
+
readonly undomanager_canUndo: (a: number) => number;
|
|
3324
|
+
readonly undomanager_canRedo: (a: number) => number;
|
|
3325
|
+
readonly undomanager_setMaxUndoSteps: (a: number, b: number) => void;
|
|
3326
|
+
readonly undomanager_setMergeInterval: (a: number, b: number) => void;
|
|
3327
|
+
readonly undomanager_addExcludeOriginPrefix: (a: number, b: number, c: number) => void;
|
|
3328
|
+
readonly undomanager_checkBinding: (a: number, b: number) => number;
|
|
3329
|
+
readonly undomanager_setOnPush: (a: number, b: number) => void;
|
|
3330
|
+
readonly undomanager_setOnPop: (a: number, b: number) => void;
|
|
3331
|
+
readonly undomanager_clear: (a: number) => void;
|
|
3332
|
+
readonly __wbg_versionvector_free: (a: number) => void;
|
|
3333
|
+
readonly versionvector_new: (a: number, b: number) => void;
|
|
3334
|
+
readonly versionvector_parseJSON: (a: number, b: number) => void;
|
|
3335
|
+
readonly versionvector_toJSON: (a: number) => number;
|
|
3336
|
+
readonly versionvector_encode: (a: number, b: number) => void;
|
|
3337
|
+
readonly versionvector_decode: (a: number, b: number, c: number) => void;
|
|
3338
|
+
readonly versionvector_get: (a: number, b: number, c: number) => void;
|
|
3339
|
+
readonly versionvector_compare: (a: number, b: number, c: number) => void;
|
|
3340
|
+
readonly decodeImportBlobMeta: (a: number, b: number, c: number) => void;
|
|
3341
|
+
readonly __wbg_loromovablelist_free: (a: number) => void;
|
|
3342
|
+
readonly loromovablelist_parent: (a: number) => number;
|
|
3343
|
+
readonly lorotext_isAttached: (a: number) => number;
|
|
3344
|
+
readonly loromap_isAttached: (a: number) => number;
|
|
3345
|
+
readonly loromovablelist_isAttached: (a: number) => number;
|
|
3346
|
+
readonly __wbindgen_export_0: (a: number, b: number) => number;
|
|
3347
|
+
readonly __wbindgen_export_1: (a: number, b: number, c: number, d: number) => number;
|
|
3348
|
+
readonly __wbindgen_export_2: WebAssembly.Table;
|
|
3349
|
+
readonly __wbindgen_export_3: (a: number, b: number, c: number) => void;
|
|
3350
|
+
readonly __wbindgen_export_4: (a: number, b: number) => void;
|
|
3351
|
+
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
|
3352
|
+
readonly __wbindgen_export_5: (a: number, b: number, c: number) => void;
|
|
3353
|
+
readonly __wbindgen_export_6: (a: number) => void;
|
|
3354
|
+
readonly __wbindgen_start: () => void;
|
|
3355
|
+
}
|
|
3356
|
+
|
|
3357
|
+
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
|
3358
|
+
/**
|
|
3359
|
+
* Instantiates the given `module`, which can either be bytes or
|
|
3360
|
+
* a precompiled `WebAssembly.Module`.
|
|
3361
|
+
*
|
|
3362
|
+
* @param {SyncInitInput} module
|
|
3363
|
+
*
|
|
3364
|
+
* @returns {InitOutput}
|
|
3365
|
+
*/
|
|
3366
|
+
export function initSync(module: SyncInitInput): InitOutput;
|
|
3367
|
+
|
|
3368
|
+
/**
|
|
3369
|
+
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
|
3370
|
+
* for everything else, calls `WebAssembly.instantiate` directly.
|
|
3371
|
+
*
|
|
3372
|
+
* @param {InitInput | Promise<InitInput>} module_or_path
|
|
3373
|
+
*
|
|
3374
|
+
* @returns {Promise<InitOutput>}
|
|
3375
|
+
*/
|
|
3376
|
+
export default function __wbg_init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|