loro-crdt 0.13.1 → 0.14.0
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 +35 -0
- package/dist/loro.d.ts +193 -26
- package/dist/loro.js +0 -28
- package/dist/loro.js.map +1 -1
- package/dist/loro.mjs +0 -29
- package/dist/loro.mjs.map +1 -1
- package/dist/src/index.js +106 -0
- package/dist/tests/basic.test.js +415 -0
- package/dist/tests/checkout.test.js +76 -0
- package/dist/tests/event.test.js +345 -0
- package/dist/tests/issue.test.js +59 -0
- package/dist/tests/misc.test.js +245 -0
- package/dist/tests/richtext.test.js +197 -0
- package/dist/tests/type.test.js +22 -0
- package/dist/tests/version.test.js +185 -0
- package/dist/vite.config.js +14 -0
- package/package.json +3 -3
- package/src/index.ts +202 -65
- package/tsconfig.json +2 -2
package/src/index.ts
CHANGED
|
@@ -8,41 +8,11 @@ import {
|
|
|
8
8
|
LoroMap,
|
|
9
9
|
LoroText,
|
|
10
10
|
LoroTree,
|
|
11
|
-
LoroTreeNode,
|
|
12
11
|
OpId,
|
|
13
12
|
TreeID,
|
|
14
13
|
Value,
|
|
15
14
|
} from "loro-wasm";
|
|
16
15
|
|
|
17
|
-
Loro.prototype.getTypedMap = function (...args) {
|
|
18
|
-
return this.getMap(...args);
|
|
19
|
-
};
|
|
20
|
-
Loro.prototype.getTypedList = function (...args) {
|
|
21
|
-
return this.getList(...args);
|
|
22
|
-
};
|
|
23
|
-
LoroList.prototype.getTyped = function (loro, index) {
|
|
24
|
-
const value = this.get(index);
|
|
25
|
-
if (typeof value === "string" && isContainerId(value)) {
|
|
26
|
-
return loro.getContainerById(value);
|
|
27
|
-
} else {
|
|
28
|
-
return value;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
LoroList.prototype.insertTyped = function (...args) {
|
|
32
|
-
return this.insert(...args);
|
|
33
|
-
};
|
|
34
|
-
LoroMap.prototype.getTyped = function (loro, key) {
|
|
35
|
-
const value = this.get(key);
|
|
36
|
-
if (typeof value === "string" && isContainerId(value)) {
|
|
37
|
-
return loro.getContainerById(value);
|
|
38
|
-
} else {
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
LoroMap.prototype.setTyped = function (...args) {
|
|
43
|
-
return this.set(...args);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
16
|
export type Frontiers = OpId[];
|
|
47
17
|
|
|
48
18
|
/**
|
|
@@ -56,18 +26,21 @@ export type Path = (number | string | TreeID)[];
|
|
|
56
26
|
/**
|
|
57
27
|
* A batch of events that created by a single `import`/`transaction`/`checkout`.
|
|
58
28
|
*
|
|
59
|
-
* @prop
|
|
29
|
+
* @prop by - How the event is triggered.
|
|
60
30
|
* @prop origin - (Optional) Provides information about the origin of the event.
|
|
61
31
|
* @prop diff - Contains the differential information related to the event.
|
|
62
32
|
* @prop target - Identifies the container ID of the event's target.
|
|
63
33
|
* @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.
|
|
64
34
|
*/
|
|
65
35
|
export interface LoroEventBatch {
|
|
66
|
-
local: boolean;
|
|
67
36
|
/**
|
|
68
|
-
*
|
|
37
|
+
* How the event is triggered.
|
|
38
|
+
*
|
|
39
|
+
* - `local`: The event is triggered by a local transaction.
|
|
40
|
+
* - `import`: The event is triggered by an import operation.
|
|
41
|
+
* - `checkout`: The event is triggered by a checkout operation.
|
|
69
42
|
*/
|
|
70
|
-
|
|
43
|
+
by: "local" | "import" | "checkout";
|
|
71
44
|
origin?: string;
|
|
72
45
|
/**
|
|
73
46
|
* The container ID of the current event receiver.
|
|
@@ -196,52 +169,211 @@ declare module "loro-wasm" {
|
|
|
196
169
|
subscribe(listener: Listener): number;
|
|
197
170
|
}
|
|
198
171
|
|
|
199
|
-
interface Loro<
|
|
200
|
-
|
|
172
|
+
interface Loro<
|
|
173
|
+
T extends Record<string, Container> = Record<string, Container>,
|
|
174
|
+
> {
|
|
175
|
+
/**
|
|
176
|
+
* Get a LoroMap by container id
|
|
177
|
+
*
|
|
178
|
+
* The object returned is a new js object each time because it need to cross
|
|
179
|
+
* the WASM boundary.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* import { Loro } from "loro-crdt";
|
|
184
|
+
*
|
|
185
|
+
* const doc = new Loro();
|
|
186
|
+
* const map = doc.getMap("map");
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
getMap<Key extends keyof T>(
|
|
190
|
+
name: Key,
|
|
191
|
+
): T[Key] extends LoroMap ? T[Key] : LoroMap;
|
|
192
|
+
/**
|
|
193
|
+
* Get a LoroList by container id
|
|
194
|
+
*
|
|
195
|
+
* The object returned is a new js object each time because it need to cross
|
|
196
|
+
* the WASM boundary.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* import { Loro } from "loro-crdt";
|
|
201
|
+
*
|
|
202
|
+
* const doc = new Loro();
|
|
203
|
+
* const list = doc.getList("list");
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
getList<Key extends keyof T>(
|
|
201
207
|
name: Key,
|
|
202
|
-
): T[Key] extends
|
|
203
|
-
|
|
208
|
+
): T[Key] extends LoroList ? T[Key] : LoroList;
|
|
209
|
+
/**
|
|
210
|
+
* Get a LoroTree by container id
|
|
211
|
+
*
|
|
212
|
+
* The object returned is a new js object each time because it need to cross
|
|
213
|
+
* the WASM boundary.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* import { Loro } from "loro-crdt";
|
|
218
|
+
*
|
|
219
|
+
* const doc = new Loro();
|
|
220
|
+
* const tree = doc.getTree("tree");
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
getTree<Key extends keyof T>(
|
|
204
224
|
name: Key,
|
|
205
|
-
): T[Key] extends
|
|
206
|
-
getMap(key: string | ContainerID): LoroMap<T[string]>;
|
|
207
|
-
getList(key: string | ContainerID): LoroList<T[string]>;
|
|
208
|
-
getTree(key: string | ContainerID): LoroTree<T[string]>;
|
|
225
|
+
): T[Key] extends LoroTree ? T[Key] : LoroTree;
|
|
209
226
|
getText(key: string | ContainerID): LoroText;
|
|
210
227
|
}
|
|
211
228
|
|
|
212
|
-
interface LoroList<
|
|
213
|
-
T extends any[] = any[],
|
|
214
|
-
> {
|
|
229
|
+
interface LoroList<T = unknown> {
|
|
215
230
|
new (): LoroList<T>;
|
|
231
|
+
/**
|
|
232
|
+
* Get elements of the list. If the value is a child container, the corresponding
|
|
233
|
+
* `Container` will be returned.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```ts
|
|
237
|
+
* import { Loro } from "loro-crdt";
|
|
238
|
+
*
|
|
239
|
+
* const doc = new Loro();
|
|
240
|
+
* const list = doc.getList("list");
|
|
241
|
+
* list.insert(0, 100);
|
|
242
|
+
* list.insert(1, "foo");
|
|
243
|
+
* list.insert(2, true);
|
|
244
|
+
* list.insertContainer(3, new LoroText());
|
|
245
|
+
* console.log(list.value); // [100, "foo", true, LoroText];
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
toArray(): T[];
|
|
249
|
+
/**
|
|
250
|
+
* Insert a container at the index.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```ts
|
|
254
|
+
* import { Loro } from "loro-crdt";
|
|
255
|
+
*
|
|
256
|
+
* const doc = new Loro();
|
|
257
|
+
* const list = doc.getList("list");
|
|
258
|
+
* list.insert(0, 100);
|
|
259
|
+
* const text = list.insertContainer(1, new LoroText());
|
|
260
|
+
* text.insert(0, "Hello");
|
|
261
|
+
* console.log(list.getDeepValue()); // [100, "Hello"];
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
216
264
|
insertContainer<C extends Container>(
|
|
217
265
|
pos: number,
|
|
218
266
|
child: C,
|
|
219
|
-
): C;
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
267
|
+
): T extends C ? T : C;
|
|
268
|
+
/**
|
|
269
|
+
* Get the value at the index. If the value is a container, the corresponding handler will be returned.
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```ts
|
|
273
|
+
* import { Loro } from "loro-crdt";
|
|
274
|
+
*
|
|
275
|
+
* const doc = new Loro();
|
|
276
|
+
* const list = doc.getList("list");
|
|
277
|
+
* list.insert(0, 100);
|
|
278
|
+
* console.log(list.get(0)); // 100
|
|
279
|
+
* console.log(list.get(1)); // undefined
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
get(index: number): T;
|
|
283
|
+
/**
|
|
284
|
+
* Insert a value at index.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```ts
|
|
288
|
+
* import { Loro } from "loro-crdt";
|
|
289
|
+
*
|
|
290
|
+
* const doc = new Loro();
|
|
291
|
+
* const list = doc.getList("list");
|
|
292
|
+
* list.insert(0, 100);
|
|
293
|
+
* list.insert(1, "foo");
|
|
294
|
+
* list.insert(2, true);
|
|
295
|
+
* console.log(list.value); // [100, "foo", true];
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
insert(pos: number, value: Exclude<T, Container>): void;
|
|
224
299
|
delete(pos: number, len: number): void;
|
|
225
300
|
subscribe(txn: Loro, listener: Listener): number;
|
|
226
301
|
getAttached(): undefined | LoroList<T>;
|
|
227
302
|
}
|
|
228
303
|
|
|
229
304
|
interface LoroMap<
|
|
230
|
-
T extends Record<string,
|
|
305
|
+
T extends Record<string, unknown> = Record<string, unknown>,
|
|
231
306
|
> {
|
|
232
307
|
new (): LoroMap<T>;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
308
|
+
/**
|
|
309
|
+
* Get the value of the key. If the value is a child container, the corresponding
|
|
310
|
+
* `Container` will be returned.
|
|
311
|
+
*
|
|
312
|
+
* The object returned is a new js object each time because it need to cross
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* ```ts
|
|
316
|
+
* import { Loro } from "loro-crdt";
|
|
317
|
+
*
|
|
318
|
+
* const doc = new Loro();
|
|
319
|
+
* const map = doc.getMap("map");
|
|
320
|
+
* map.set("foo", "bar");
|
|
321
|
+
* const bar = map.get("foo");
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
getOrCreateContainer<C extends Container>(key: string, child: C): C;
|
|
325
|
+
/**
|
|
326
|
+
* Set the key with a container.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```ts
|
|
330
|
+
* import { Loro } from "loro-crdt";
|
|
331
|
+
*
|
|
332
|
+
* const doc = new Loro();
|
|
333
|
+
* const map = doc.getMap("map");
|
|
334
|
+
* map.set("foo", "bar");
|
|
335
|
+
* const text = map.setContainer("text", new LoroText());
|
|
336
|
+
* const list = map.setContainer("list", new LoroText());
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
setContainer<C extends Container, Key extends keyof T>(
|
|
340
|
+
key: Key,
|
|
239
341
|
child: C,
|
|
240
|
-
): C;
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
342
|
+
): NonNullableType<T[Key]> extends C ? NonNullableType<T[Key]> : C;
|
|
343
|
+
/**
|
|
344
|
+
* Get the value of the key. If the value is a child container, the corresponding
|
|
345
|
+
* `Container` will be returned.
|
|
346
|
+
*
|
|
347
|
+
* The object/value returned is a new js object/value each time because it need to cross
|
|
348
|
+
* the WASM boundary.
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```ts
|
|
352
|
+
* import { Loro } from "loro-crdt";
|
|
353
|
+
*
|
|
354
|
+
* const doc = new Loro();
|
|
355
|
+
* const map = doc.getMap("map");
|
|
356
|
+
* map.set("foo", "bar");
|
|
357
|
+
* const bar = map.get("foo");
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
get<Key extends keyof T>(key: Key): T[Key];
|
|
361
|
+
/**
|
|
362
|
+
* Set the key with the value.
|
|
363
|
+
*
|
|
364
|
+
* If the value of the key is exist, the old value will be updated.
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```ts
|
|
368
|
+
* import { Loro } from "loro-crdt";
|
|
369
|
+
*
|
|
370
|
+
* const doc = new Loro();
|
|
371
|
+
* const map = doc.getMap("map");
|
|
372
|
+
* map.set("foo", "bar");
|
|
373
|
+
* map.set("foo", "baz");
|
|
374
|
+
* ```
|
|
375
|
+
*/
|
|
376
|
+
set<Key extends keyof T>(key: Key, value: Exclude<T[Key], Container>): void;
|
|
245
377
|
delete(key: string): void;
|
|
246
378
|
subscribe(txn: Loro, listener: Listener): number;
|
|
247
379
|
}
|
|
@@ -254,7 +386,7 @@ declare module "loro-wasm" {
|
|
|
254
386
|
}
|
|
255
387
|
|
|
256
388
|
interface LoroTree<
|
|
257
|
-
T extends Record<string,
|
|
389
|
+
T extends Record<string, unknown> = Record<string, unknown>,
|
|
258
390
|
> {
|
|
259
391
|
new (): LoroTree<T>;
|
|
260
392
|
createNode(parent: TreeID | undefined): LoroTreeNode<T>;
|
|
@@ -266,13 +398,18 @@ declare module "loro-wasm" {
|
|
|
266
398
|
}
|
|
267
399
|
|
|
268
400
|
interface LoroTreeNode<
|
|
269
|
-
T extends Record<string,
|
|
401
|
+
T extends Record<string, unknown> = Record<string, unknown>,
|
|
270
402
|
> {
|
|
403
|
+
/**
|
|
404
|
+
* Get the associated metadata map container of a tree node.
|
|
405
|
+
*/
|
|
271
406
|
readonly data: LoroMap<T>;
|
|
272
407
|
createNode(): LoroTreeNode<T>;
|
|
273
408
|
setAsRoot(): void;
|
|
274
409
|
moveTo(parent: LoroTreeNode<T>): void;
|
|
275
|
-
parent(): LoroTreeNode | undefined;
|
|
410
|
+
parent(): LoroTreeNode<T> | undefined;
|
|
276
411
|
children(): Array<LoroTreeNode<T>>;
|
|
277
412
|
}
|
|
278
413
|
}
|
|
414
|
+
|
|
415
|
+
type NonNullableType<T> = Exclude<T, null | undefined>;
|
package/tsconfig.json
CHANGED
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
|
51
51
|
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
|
52
52
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
|
53
|
-
"outDir": "./dist"
|
|
53
|
+
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
|
54
54
|
// "removeComments": true, /* Disable emitting comments. */
|
|
55
|
-
|
|
55
|
+
"noEmit": true /* Disable emitting files from a compilation. */,
|
|
56
56
|
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
|
57
57
|
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
|
58
58
|
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|