loro-crdt 0.13.0 → 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/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 local - Indicates whether the event is local.
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
- * If true, this event was triggered by a checkout.
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
- fromCheckout: boolean;
43
+ by: "local" | "import" | "checkout";
71
44
  origin?: string;
72
45
  /**
73
46
  * The container ID of the current event receiver.
@@ -180,12 +153,12 @@ export function isContainer(value: any): value is Container {
180
153
  export function getType<T>(
181
154
  value: T,
182
155
  ): T extends LoroText ? "Text"
183
- : T extends LoroMap ? "Map"
184
- : T extends LoroTree ? "Tree"
185
- : T extends LoroList ? "List"
156
+ : T extends LoroMap<any> ? "Map"
157
+ : T extends LoroTree<any> ? "Tree"
158
+ : T extends LoroList<any> ? "List"
186
159
  : "Json" {
187
160
  if (isContainer(value)) {
188
- return value.kind();
161
+ return value.kind() as unknown as any;
189
162
  }
190
163
 
191
164
  return "Json" as any;
@@ -196,52 +169,227 @@ declare module "loro-wasm" {
196
169
  subscribe(listener: Listener): number;
197
170
  }
198
171
 
199
- interface Loro<T extends Record<string, any> = Record<string, any>> {
200
- getTypedMap<Key extends keyof T & string>(
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>(
201
190
  name: Key,
202
- ): T[Key] extends LoroMap ? T[Key] : never;
203
- getTypedList<Key extends keyof T & string>(
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>(
204
207
  name: Key,
205
- ): T[Key] extends LoroList ? T[Key] : never;
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>(
224
+ name: Key,
225
+ ): T[Key] extends LoroTree ? T[Key] : LoroTree;
226
+ getText(key: string | ContainerID): LoroText;
206
227
  }
207
228
 
208
- interface LoroList<T extends any[] = any[]> {
209
- insertContainer<C extends Container>(pos: number, child: C): C;
210
-
211
- get(index: number): undefined | Value | Container;
212
- getTyped<Key extends keyof T & number>(loro: Loro, index: Key): T[Key];
213
- insertTyped<Key extends keyof T & number>(pos: Key, value: T[Key]): void;
214
- insert(pos: number, value: Container): never;
215
- insert(pos: number, value: Value): void;
229
+ interface LoroList<T = unknown> {
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
+ */
264
+ insertContainer<C extends Container>(
265
+ pos: number,
266
+ child: C,
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;
216
299
  delete(pos: number, len: number): void;
217
300
  subscribe(txn: Loro, listener: Listener): number;
301
+ getAttached(): undefined | LoroList<T>;
218
302
  }
219
303
 
220
- interface LoroMap<T extends Record<string, any> = Record<string, any>> {
221
- getOrCreateContainer(key: string, container_type: "Map"): LoroMap;
222
- getOrCreateContainer(key: string, container_type: "List"): LoroList;
223
- getOrCreateContainer(key: string, container_type: "Text"): LoroText;
224
- getOrCreateContainer(key: string, container_type: "Tree"): LoroTree;
225
- getOrCreateContainer(key: string, container_type: string): never;
226
-
227
- setContainer<C extends Container>(key: string, child: C): C;
228
-
229
- get(key: string): undefined | Value | Container;
230
- getTyped<Key extends keyof T & string>(txn: Loro, key: Key): T[Key];
231
- set(key: string, value: Value): void;
232
- setTyped<Key extends keyof T & string>(key: Key, value: T[Key]): void;
304
+ interface LoroMap<
305
+ T extends Record<string, unknown> = Record<string, unknown>,
306
+ > {
307
+ new (): LoroMap<T>;
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,
341
+ child: C,
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;
233
377
  delete(key: string): void;
234
378
  subscribe(txn: Loro, listener: Listener): number;
235
379
  }
236
380
 
237
381
  interface LoroText {
382
+ new (): LoroText;
238
383
  insert(pos: number, text: string): void;
239
384
  delete(pos: number, len: number): void;
240
385
  subscribe(txn: Loro, listener: Listener): number;
241
386
  }
242
387
 
243
- interface LoroTree {
244
- createNode(parent: TreeID | undefined): LoroTreeNode;
388
+ interface LoroTree<
389
+ T extends Record<string, unknown> = Record<string, unknown>,
390
+ > {
391
+ new (): LoroTree<T>;
392
+ createNode(parent: TreeID | undefined): LoroTreeNode<T>;
245
393
  move(target: TreeID, parent: TreeID | undefined): void;
246
394
  delete(target: TreeID): void;
247
395
  has(target: TreeID): boolean;
@@ -249,12 +397,19 @@ declare module "loro-wasm" {
249
397
  subscribe(txn: Loro, listener: Listener): number;
250
398
  }
251
399
 
252
- interface LoroTreeNode {
253
- readonly data: LoroMap;
254
- createNode(): LoroTreeNode;
400
+ interface LoroTreeNode<
401
+ T extends Record<string, unknown> = Record<string, unknown>,
402
+ > {
403
+ /**
404
+ * Get the associated metadata map container of a tree node.
405
+ */
406
+ readonly data: LoroMap<T>;
407
+ createNode(): LoroTreeNode<T>;
255
408
  setAsRoot(): void;
256
- moveTo(parent: LoroTreeNode): void;
257
- parent(): LoroTreeNode | undefined;
258
- children(): Array<LoroTreeNode>;
409
+ moveTo(parent: LoroTreeNode<T>): void;
410
+ parent(): LoroTreeNode<T> | undefined;
411
+ children(): Array<LoroTreeNode<T>>;
259
412
  }
260
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", /* Specify an output folder for all emitted files. */
53
+ "outDir": "./dist" /* Specify an output folder for all emitted files. */,
54
54
  // "removeComments": true, /* Disable emitting comments. */
55
- // "noEmit": true, /* Disable emitting files from a compilation. */
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. */