loro-crdt 0.16.12 → 1.0.0-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/README.md CHANGED
@@ -40,9 +40,6 @@
40
40
 
41
41
  https://github.com/loro-dev/loro/assets/18425020/fe246c47-a120-44b3-91d4-1e7232a5b4ac
42
42
 
43
-
44
- > ⚠️ **Notice**: The current API and encoding schema of Loro are **experimental** and **subject to change**. You should not use it in production.
45
-
46
43
  Loro is a [CRDTs(Conflict-free Replicated Data Types)](https://crdt.tech/) library that makes building [local-first apps][local-first] easier. It is currently available for JavaScript (via WASM) and Rust developers.
47
44
 
48
45
  Explore our vision in our blog: [**✨ Reimagine State Management with CRDTs**](https://loro.dev/blog/loro-now-open-source).
package/dist/loro.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { Value, AwarenessWasm, PeerID as PeerID$1, Container, ContainerID, TreeID, OpId, Delta, LoroText, LoroMap, LoroTree, LoroList, LoroCounter } from 'loro-wasm';
2
- export * from 'loro-wasm';
3
- export { Loro } from 'loro-wasm';
1
+ import { Value, AwarenessWasm, PeerID as PeerID$1, Container, ContainerID, TreeID, LoroDoc, OpId, Delta, LoroText, LoroMap, LoroTree, LoroList, LoroCounter } from 'loro-wasm';
2
+ export { AwarenessWasm, Change, Container, ContainerID, ContainerType, Cursor, Delta, ExportMode, ImportBlobMetadata, JsonChange, JsonContainerID, JsonOp, JsonOpID, JsonSchema, JsonValue, ListOp, LoroCounter, LoroDoc, LoroList, LoroMap, LoroMovableList, LoroText, LoroTree, LoroTreeNode, MapOp, MovableListOp, OpId, PeerID, Side, TextOp, TreeID, TreeNodeValue, TreeOp, UndoConfig, UndoManager, UnknownOp, Value, VersionVector, decodeImportBlobMeta, newContainerID, newRootContainerID, setDebug } from 'loro-wasm';
4
3
 
5
4
  type AwarenessListener = (arg: {
6
5
  updated: PeerID$1[];
@@ -33,6 +32,12 @@ declare class Awareness<T extends Value = Value> {
33
32
  private startTimerIfNotEmpty;
34
33
  }
35
34
 
35
+ /**
36
+ * @deprecated Please use LoroDoc
37
+ */
38
+ declare class Loro extends LoroDoc {
39
+ }
40
+
36
41
  type Frontiers = OpId[];
37
42
  /**
38
43
  * Represents a path to identify the exact location of an event's target.
@@ -98,16 +103,20 @@ type TreeDiffItem = {
98
103
  action: "create";
99
104
  parent: TreeID | undefined;
100
105
  index: number;
101
- position: string;
106
+ fractional_index: string;
102
107
  } | {
103
108
  target: TreeID;
104
109
  action: "delete";
110
+ old_parent: TreeID | undefined;
111
+ old_index: number;
105
112
  } | {
106
113
  target: TreeID;
107
114
  action: "move";
108
115
  parent: TreeID | undefined;
109
116
  index: number;
110
- position: string;
117
+ fractional_index: string;
118
+ old_parent: TreeID | undefined;
119
+ old_index: number;
111
120
  };
112
121
  type TreeDiff = {
113
122
  type: "tree";
@@ -122,13 +131,12 @@ interface Listener {
122
131
  (event: LoroEventBatch): void;
123
132
  }
124
133
  declare function isContainerId(s: string): s is ContainerID;
125
-
126
134
  /** Whether the value is a container.
127
135
  *
128
136
  * # Example
129
137
  *
130
138
  * ```ts
131
- * const doc = new Loro();
139
+ * const doc = new LoroDoc();
132
140
  * const map = doc.getMap("map");
133
141
  * const list = doc.getList("list");
134
142
  * const text = doc.getText("text");
@@ -145,7 +153,7 @@ declare function isContainer(value: any): value is Container;
145
153
  * # Example
146
154
  *
147
155
  * ```ts
148
- * const doc = new Loro();
156
+ * const doc = new LoroDoc();
149
157
  * const map = doc.getMap("map");
150
158
  * const list = doc.getList("list");
151
159
  * const text = doc.getText("text");
@@ -159,7 +167,7 @@ declare function isContainer(value: any): value is Container;
159
167
  */
160
168
  declare function getType<T>(value: T): T extends LoroText ? "Text" : T extends LoroMap<any> ? "Map" : T extends LoroTree<any> ? "Tree" : T extends LoroList<any> ? "List" : T extends LoroCounter ? "Counter" : "Json";
161
169
  declare module "loro-wasm" {
162
- interface Loro {
170
+ interface LoroDoc {
163
171
  subscribe(listener: Listener): number;
164
172
  }
165
173
  interface UndoManager {
@@ -178,7 +186,7 @@ declare module "loro-wasm" {
178
186
  */
179
187
  setOnPop(listener?: UndoConfig["onPop"]): void;
180
188
  }
181
- interface Loro<T extends Record<string, Container> = Record<string, Container>> {
189
+ interface LoroDoc<T extends Record<string, Container> = Record<string, Container>> {
182
190
  /**
183
191
  * Get a LoroMap by container id
184
192
  *
@@ -187,9 +195,9 @@ declare module "loro-wasm" {
187
195
  *
188
196
  * @example
189
197
  * ```ts
190
- * import { Loro } from "loro-crdt";
198
+ * import { LoroDoc } from "loro-crdt";
191
199
  *
192
- * const doc = new Loro();
200
+ * const doc = new LoroDoc();
193
201
  * const map = doc.getMap("map");
194
202
  * ```
195
203
  */
@@ -202,9 +210,9 @@ declare module "loro-wasm" {
202
210
  *
203
211
  * @example
204
212
  * ```ts
205
- * import { Loro } from "loro-crdt";
213
+ * import { LoroDoc } from "loro-crdt";
206
214
  *
207
- * const doc = new Loro();
215
+ * const doc = new LoroDoc();
208
216
  * const list = doc.getList("list");
209
217
  * ```
210
218
  */
@@ -217,9 +225,9 @@ declare module "loro-wasm" {
217
225
  *
218
226
  * @example
219
227
  * ```ts
220
- * import { Loro } from "loro-crdt";
228
+ * import { LoroDoc } from "loro-crdt";
221
229
  *
222
- * const doc = new Loro();
230
+ * const doc = new LoroDoc();
223
231
  * const list = doc.getList("list");
224
232
  * ```
225
233
  */
@@ -232,9 +240,9 @@ declare module "loro-wasm" {
232
240
  *
233
241
  * @example
234
242
  * ```ts
235
- * import { Loro } from "loro-crdt";
243
+ * import { LoroDoc } from "loro-crdt";
236
244
  *
237
- * const doc = new Loro();
245
+ * const doc = new LoroDoc();
238
246
  * const tree = doc.getTree("tree");
239
247
  * ```
240
248
  */
@@ -249,9 +257,9 @@ declare module "loro-wasm" {
249
257
  *
250
258
  * @example
251
259
  * ```ts
252
- * import { Loro } from "loro-crdt";
260
+ * import { LoroDoc } from "loro-crdt";
253
261
  *
254
- * const doc = new Loro();
262
+ * const doc = new LoroDoc();
255
263
  * const list = doc.getList("list");
256
264
  * list.insert(0, 100);
257
265
  * list.insert(1, "foo");
@@ -266,9 +274,9 @@ declare module "loro-wasm" {
266
274
  *
267
275
  * @example
268
276
  * ```ts
269
- * import { Loro, LoroText } from "loro-crdt";
277
+ * import { LoroDoc, LoroText } from "loro-crdt";
270
278
  *
271
- * const doc = new Loro();
279
+ * const doc = new LoroDoc();
272
280
  * const list = doc.getList("list");
273
281
  * list.insert(0, 100);
274
282
  * const text = list.insertContainer(1, new LoroText());
@@ -282,9 +290,9 @@ declare module "loro-wasm" {
282
290
  *
283
291
  * @example
284
292
  * ```ts
285
- * import { Loro } from "loro-crdt";
293
+ * import { LoroDoc } from "loro-crdt";
286
294
  *
287
- * const doc = new Loro();
295
+ * const doc = new LoroDoc();
288
296
  * const list = doc.getList("list");
289
297
  * list.insert(0, 100);
290
298
  * console.log(list.get(0)); // 100
@@ -297,9 +305,9 @@ declare module "loro-wasm" {
297
305
  *
298
306
  * @example
299
307
  * ```ts
300
- * import { Loro } from "loro-crdt";
308
+ * import { LoroDoc } from "loro-crdt";
301
309
  *
302
- * const doc = new Loro();
310
+ * const doc = new LoroDoc();
303
311
  * const list = doc.getList("list");
304
312
  * list.insert(0, 100);
305
313
  * list.insert(1, "foo");
@@ -321,9 +329,9 @@ declare module "loro-wasm" {
321
329
  *
322
330
  * @example
323
331
  * ```ts
324
- * import { Loro, LoroText } from "loro-crdt";
332
+ * import { LoroDoc, LoroText } from "loro-crdt";
325
333
  *
326
- * const doc = new Loro();
334
+ * const doc = new LoroDoc();
327
335
  * const list = doc.getMovableList("list");
328
336
  * list.insert(0, 100);
329
337
  * list.insert(1, "foo");
@@ -338,9 +346,9 @@ declare module "loro-wasm" {
338
346
  *
339
347
  * @example
340
348
  * ```ts
341
- * import { Loro } from "loro-crdt";
349
+ * import { LoroDoc } from "loro-crdt";
342
350
  *
343
- * const doc = new Loro();
351
+ * const doc = new LoroDoc();
344
352
  * const list = doc.getMovableList("list");
345
353
  * list.insert(0, 100);
346
354
  * const text = list.insertContainer(1, new LoroText());
@@ -354,10 +362,10 @@ declare module "loro-wasm" {
354
362
  *
355
363
  * @example
356
364
  * ```ts
357
- * import { Loro } from "loro-crdt";
365
+ * import { LoroDoc } from "loro-crdt";
358
366
  *
359
- * const doc = new Loro();
360
- * const list = doc.getMoableList("list");
367
+ * const doc = new LoroDoc();
368
+ * const list = doc.getMovableList("list");
361
369
  * list.insert(0, 100);
362
370
  * console.log(list.get(0)); // 100
363
371
  * console.log(list.get(1)); // undefined
@@ -369,9 +377,9 @@ declare module "loro-wasm" {
369
377
  *
370
378
  * @example
371
379
  * ```ts
372
- * import { Loro } from "loro-crdt";
380
+ * import { LoroDoc } from "loro-crdt";
373
381
  *
374
- * const doc = new Loro();
382
+ * const doc = new LoroDoc();
375
383
  * const list = doc.getMovableList("list");
376
384
  * list.insert(0, 100);
377
385
  * list.insert(1, "foo");
@@ -397,9 +405,9 @@ declare module "loro-wasm" {
397
405
  *
398
406
  * @example
399
407
  * ```ts
400
- * import { Loro } from "loro-crdt";
408
+ * import { LoroDoc } from "loro-crdt";
401
409
  *
402
- * const doc = new Loro();
410
+ * const doc = new LoroDoc();
403
411
  * const list = doc.getList("list");
404
412
  * list.insert(0, 100);
405
413
  * list.insert(1, "foo");
@@ -414,9 +422,9 @@ declare module "loro-wasm" {
414
422
  *
415
423
  * @example
416
424
  * ```ts
417
- * import { Loro } from "loro-crdt";
425
+ * import { LoroDoc } from "loro-crdt";
418
426
  *
419
- * const doc = new Loro();
427
+ * const doc = new LoroDoc();
420
428
  * const list = doc.getMovableList("list");
421
429
  * list.insert(0, 100);
422
430
  * const text = list.setContainer(0, new LoroText());
@@ -436,9 +444,9 @@ declare module "loro-wasm" {
436
444
  *
437
445
  * @example
438
446
  * ```ts
439
- * import { Loro } from "loro-crdt";
447
+ * import { LoroDoc } from "loro-crdt";
440
448
  *
441
- * const doc = new Loro();
449
+ * const doc = new LoroDoc();
442
450
  * const map = doc.getMap("map");
443
451
  * map.set("foo", "bar");
444
452
  * const bar = map.get("foo");
@@ -450,9 +458,9 @@ declare module "loro-wasm" {
450
458
  *
451
459
  * @example
452
460
  * ```ts
453
- * import { Loro } from "loro-crdt";
461
+ * import { LoroDoc } from "loro-crdt";
454
462
  *
455
- * const doc = new Loro();
463
+ * const doc = new LoroDoc();
456
464
  * const map = doc.getMap("map");
457
465
  * map.set("foo", "bar");
458
466
  * const text = map.setContainer("text", new LoroText());
@@ -469,9 +477,9 @@ declare module "loro-wasm" {
469
477
  *
470
478
  * @example
471
479
  * ```ts
472
- * import { Loro } from "loro-crdt";
480
+ * import { LoroDoc } from "loro-crdt";
473
481
  *
474
- * const doc = new Loro();
482
+ * const doc = new LoroDoc();
475
483
  * const map = doc.getMap("map");
476
484
  * map.set("foo", "bar");
477
485
  * const bar = map.get("foo");
@@ -485,9 +493,9 @@ declare module "loro-wasm" {
485
493
  *
486
494
  * @example
487
495
  * ```ts
488
- * import { Loro } from "loro-crdt";
496
+ * import { LoroDoc } from "loro-crdt";
489
497
  *
490
- * const doc = new Loro();
498
+ * const doc = new LoroDoc();
491
499
  * const map = doc.getMap("map");
492
500
  * map.set("foo", "bar");
493
501
  * map.set("foo", "baz");
@@ -513,9 +521,9 @@ declare module "loro-wasm" {
513
521
  *
514
522
  * @example
515
523
  * ```ts
516
- * import { Loro } from "loro-crdt";
524
+ * import { LoroDoc } from "loro-crdt";
517
525
  *
518
- * const doc = new Loro();
526
+ * const doc = new LoroDoc();
519
527
  * const tree = doc.getTree("tree");
520
528
  * const root = tree.createNode();
521
529
  * const node = tree.createNode(undefined, 0);
@@ -548,9 +556,9 @@ declare module "loro-wasm" {
548
556
  *
549
557
  * @example
550
558
  * ```typescript
551
- * import { Loro } from "loro-crdt";
559
+ * import { LoroDoc } from "loro-crdt";
552
560
  *
553
- * let doc = new Loro();
561
+ * let doc = new LoroDoc();
554
562
  * let tree = doc.getTree("tree");
555
563
  * let root = tree.createNode();
556
564
  * let node = root.createNode();
@@ -581,4 +589,4 @@ declare module "loro-wasm" {
581
589
  }
582
590
  type NonNullableType<T> = Exclude<T, null | undefined>;
583
591
 
584
- export { Awareness, CounterDiff, Diff, Frontiers, ListDiff, LoroEvent, LoroEventBatch, MapDiff, Path, TextDiff, TreeDiff, TreeDiffItem, getType, isContainer, isContainerId };
592
+ export { Awareness, CounterDiff, Diff, Frontiers, ListDiff, Loro, LoroEvent, LoroEventBatch, MapDiff, Path, TextDiff, TreeDiff, TreeDiffItem, getType, isContainer, isContainerId };
package/dist/loro.js CHANGED
@@ -84,6 +84,8 @@ class Awareness {
84
84
  }
85
85
  }
86
86
 
87
+ class Loro extends loroWasm.LoroDoc {
88
+ }
87
89
  const CONTAINER_TYPES = ["Map", "Text", "List", "Tree", "MovableList", "Counter"];
88
90
  function isContainerId(s) {
89
91
  return s.startsWith("cid:");
@@ -105,18 +107,177 @@ function getType(value) {
105
107
  return "Json";
106
108
  }
107
109
 
108
- Object.defineProperty(exports, 'Loro', {
110
+ Object.defineProperty(exports, 'AwarenessWasm', {
111
+ enumerable: true,
112
+ get: function () { return loroWasm.AwarenessWasm; }
113
+ });
114
+ Object.defineProperty(exports, 'Change', {
115
+ enumerable: true,
116
+ get: function () { return loroWasm.Change; }
117
+ });
118
+ Object.defineProperty(exports, 'Container', {
119
+ enumerable: true,
120
+ get: function () { return loroWasm.Container; }
121
+ });
122
+ Object.defineProperty(exports, 'ContainerID', {
123
+ enumerable: true,
124
+ get: function () { return loroWasm.ContainerID; }
125
+ });
126
+ Object.defineProperty(exports, 'ContainerType', {
127
+ enumerable: true,
128
+ get: function () { return loroWasm.ContainerType; }
129
+ });
130
+ Object.defineProperty(exports, 'Cursor', {
131
+ enumerable: true,
132
+ get: function () { return loroWasm.Cursor; }
133
+ });
134
+ Object.defineProperty(exports, 'Delta', {
135
+ enumerable: true,
136
+ get: function () { return loroWasm.Delta; }
137
+ });
138
+ Object.defineProperty(exports, 'ExportMode', {
139
+ enumerable: true,
140
+ get: function () { return loroWasm.ExportMode; }
141
+ });
142
+ Object.defineProperty(exports, 'ImportBlobMetadata', {
143
+ enumerable: true,
144
+ get: function () { return loroWasm.ImportBlobMetadata; }
145
+ });
146
+ Object.defineProperty(exports, 'JsonChange', {
147
+ enumerable: true,
148
+ get: function () { return loroWasm.JsonChange; }
149
+ });
150
+ Object.defineProperty(exports, 'JsonContainerID', {
151
+ enumerable: true,
152
+ get: function () { return loroWasm.JsonContainerID; }
153
+ });
154
+ Object.defineProperty(exports, 'JsonOp', {
155
+ enumerable: true,
156
+ get: function () { return loroWasm.JsonOp; }
157
+ });
158
+ Object.defineProperty(exports, 'JsonOpID', {
159
+ enumerable: true,
160
+ get: function () { return loroWasm.JsonOpID; }
161
+ });
162
+ Object.defineProperty(exports, 'JsonSchema', {
163
+ enumerable: true,
164
+ get: function () { return loroWasm.JsonSchema; }
165
+ });
166
+ Object.defineProperty(exports, 'JsonValue', {
167
+ enumerable: true,
168
+ get: function () { return loroWasm.JsonValue; }
169
+ });
170
+ Object.defineProperty(exports, 'ListOp', {
171
+ enumerable: true,
172
+ get: function () { return loroWasm.ListOp; }
173
+ });
174
+ Object.defineProperty(exports, 'LoroCounter', {
175
+ enumerable: true,
176
+ get: function () { return loroWasm.LoroCounter; }
177
+ });
178
+ Object.defineProperty(exports, 'LoroDoc', {
179
+ enumerable: true,
180
+ get: function () { return loroWasm.LoroDoc; }
181
+ });
182
+ Object.defineProperty(exports, 'LoroList', {
183
+ enumerable: true,
184
+ get: function () { return loroWasm.LoroList; }
185
+ });
186
+ Object.defineProperty(exports, 'LoroMap', {
187
+ enumerable: true,
188
+ get: function () { return loroWasm.LoroMap; }
189
+ });
190
+ Object.defineProperty(exports, 'LoroMovableList', {
191
+ enumerable: true,
192
+ get: function () { return loroWasm.LoroMovableList; }
193
+ });
194
+ Object.defineProperty(exports, 'LoroText', {
195
+ enumerable: true,
196
+ get: function () { return loroWasm.LoroText; }
197
+ });
198
+ Object.defineProperty(exports, 'LoroTree', {
199
+ enumerable: true,
200
+ get: function () { return loroWasm.LoroTree; }
201
+ });
202
+ Object.defineProperty(exports, 'LoroTreeNode', {
203
+ enumerable: true,
204
+ get: function () { return loroWasm.LoroTreeNode; }
205
+ });
206
+ Object.defineProperty(exports, 'MapOp', {
207
+ enumerable: true,
208
+ get: function () { return loroWasm.MapOp; }
209
+ });
210
+ Object.defineProperty(exports, 'MovableListOp', {
211
+ enumerable: true,
212
+ get: function () { return loroWasm.MovableListOp; }
213
+ });
214
+ Object.defineProperty(exports, 'OpId', {
215
+ enumerable: true,
216
+ get: function () { return loroWasm.OpId; }
217
+ });
218
+ Object.defineProperty(exports, 'PeerID', {
219
+ enumerable: true,
220
+ get: function () { return loroWasm.PeerID; }
221
+ });
222
+ Object.defineProperty(exports, 'Side', {
223
+ enumerable: true,
224
+ get: function () { return loroWasm.Side; }
225
+ });
226
+ Object.defineProperty(exports, 'TextOp', {
227
+ enumerable: true,
228
+ get: function () { return loroWasm.TextOp; }
229
+ });
230
+ Object.defineProperty(exports, 'TreeID', {
231
+ enumerable: true,
232
+ get: function () { return loroWasm.TreeID; }
233
+ });
234
+ Object.defineProperty(exports, 'TreeNodeValue', {
109
235
  enumerable: true,
110
- get: function () { return loroWasm.Loro; }
236
+ get: function () { return loroWasm.TreeNodeValue; }
237
+ });
238
+ Object.defineProperty(exports, 'TreeOp', {
239
+ enumerable: true,
240
+ get: function () { return loroWasm.TreeOp; }
241
+ });
242
+ Object.defineProperty(exports, 'UndoConfig', {
243
+ enumerable: true,
244
+ get: function () { return loroWasm.UndoConfig; }
245
+ });
246
+ Object.defineProperty(exports, 'UndoManager', {
247
+ enumerable: true,
248
+ get: function () { return loroWasm.UndoManager; }
249
+ });
250
+ Object.defineProperty(exports, 'UnknownOp', {
251
+ enumerable: true,
252
+ get: function () { return loroWasm.UnknownOp; }
253
+ });
254
+ Object.defineProperty(exports, 'Value', {
255
+ enumerable: true,
256
+ get: function () { return loroWasm.Value; }
257
+ });
258
+ Object.defineProperty(exports, 'VersionVector', {
259
+ enumerable: true,
260
+ get: function () { return loroWasm.VersionVector; }
261
+ });
262
+ Object.defineProperty(exports, 'decodeImportBlobMeta', {
263
+ enumerable: true,
264
+ get: function () { return loroWasm.decodeImportBlobMeta; }
265
+ });
266
+ Object.defineProperty(exports, 'newContainerID', {
267
+ enumerable: true,
268
+ get: function () { return loroWasm.newContainerID; }
269
+ });
270
+ Object.defineProperty(exports, 'newRootContainerID', {
271
+ enumerable: true,
272
+ get: function () { return loroWasm.newRootContainerID; }
273
+ });
274
+ Object.defineProperty(exports, 'setDebug', {
275
+ enumerable: true,
276
+ get: function () { return loroWasm.setDebug; }
111
277
  });
112
278
  exports.Awareness = Awareness;
279
+ exports.Loro = Loro;
113
280
  exports.getType = getType;
114
281
  exports.isContainer = isContainer;
115
282
  exports.isContainerId = isContainerId;
116
- Object.keys(loroWasm).forEach(function (k) {
117
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
118
- enumerable: true,
119
- get: function () { return loroWasm[k]; }
120
- });
121
- });
122
283
  //# sourceMappingURL=loro.js.map
package/dist/loro.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"loro.js","sources":["../src/awareness.ts","../src/index.ts"],"sourcesContent":["import { AwarenessWasm, PeerID, Value } from \"loro-wasm\";\n\nexport type AwarenessListener = (\n arg: { updated: PeerID[]; added: PeerID[]; removed: PeerID[] },\n origin: \"local\" | \"timeout\" | \"remote\" | string,\n) => void;\n\n/**\n * Awareness is a structure that allows to track the ephemeral state of the peers.\n *\n * If we don't receive a state update from a peer within the timeout, we will remove their state.\n * The timeout is in milliseconds. This can be used to handle the off-line state of a peer.\n */\nexport class Awareness<T extends Value = Value> {\n inner: AwarenessWasm<T>;\n private peer: PeerID;\n private timer: number | undefined;\n private timeout: number;\n private listeners: Set<AwarenessListener> = new Set();\n constructor(peer: PeerID, timeout: number = 30000) {\n this.inner = new AwarenessWasm(peer, timeout);\n this.peer = peer;\n this.timeout = timeout;\n }\n\n apply(bytes: Uint8Array, origin = \"remote\") {\n const { updated, added } = this.inner.apply(bytes);\n this.listeners.forEach((listener) => {\n listener({ updated, added, removed: [] }, origin);\n });\n\n this.startTimerIfNotEmpty();\n }\n\n setLocalState(state: T) {\n const wasEmpty = this.inner.getState(this.peer) == null;\n this.inner.setLocalState(state);\n if (wasEmpty) {\n this.listeners.forEach((listener) => {\n listener(\n { updated: [], added: [this.inner.peer()], removed: [] },\n \"local\",\n );\n });\n } else {\n this.listeners.forEach((listener) => {\n listener(\n { updated: [this.inner.peer()], added: [], removed: [] },\n \"local\",\n );\n });\n }\n\n this.startTimerIfNotEmpty();\n }\n\n getLocalState(): T | undefined {\n return this.inner.getState(this.peer);\n }\n\n getAllStates(): Record<PeerID, T> {\n return this.inner.getAllStates();\n }\n\n encode(peers: PeerID[]): Uint8Array {\n return this.inner.encode(peers);\n }\n\n encodeAll(): Uint8Array {\n return this.inner.encodeAll();\n }\n\n addListener(listener: AwarenessListener) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: AwarenessListener) {\n this.listeners.delete(listener);\n }\n\n peers(): PeerID[] {\n return this.inner.peers();\n }\n\n destroy() {\n clearInterval(this.timer);\n this.listeners.clear();\n }\n\n private startTimerIfNotEmpty() {\n if (this.inner.isEmpty() || this.timer != null) {\n return;\n }\n\n this.timer = setInterval(() => {\n const removed = this.inner.removeOutdated();\n if (removed.length > 0) {\n this.listeners.forEach((listener) => {\n listener({ updated: [], added: [], removed }, \"timeout\");\n });\n }\n if (this.inner.isEmpty()) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n }, this.timeout / 2) as unknown as number;\n }\n}\n","export * from \"loro-wasm\";\nimport {\n Container,\n ContainerID,\n Delta,\n Loro,\n LoroList,\n LoroMap,\n LoroText,\n LoroTree,\n LoroCounter,\n OpId,\n TreeID,\n Value,\n} from \"loro-wasm\";\nexport { Awareness } from \"./awareness\";\n\nexport type Frontiers = OpId[];\n\n/**\n * Represents a path to identify the exact location of an event's target.\n * The path is composed of numbers (e.g., indices of a list container) strings\n * (e.g., keys of a map container) and TreeID (the node of a tree container),\n * indicating the absolute position of the event's source within a loro document.\n */\nexport type Path = (number | string | TreeID)[];\n\n/**\n * A batch of events that created by a single `import`/`transaction`/`checkout`.\n *\n * @prop by - How the event is triggered.\n * @prop origin - (Optional) Provides information about the origin of the event.\n * @prop diff - Contains the differential information related to the event.\n * @prop target - Identifies the container ID of the event's target.\n * @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.\n */\nexport interface LoroEventBatch {\n /**\n * How the event is triggered.\n *\n * - `local`: The event is triggered by a local transaction.\n * - `import`: The event is triggered by an import operation.\n * - `checkout`: The event is triggered by a checkout operation.\n */\n by: \"local\" | \"import\" | \"checkout\";\n origin?: string;\n /**\n * The container ID of the current event receiver.\n * It's undefined if the subscriber is on the root document.\n */\n currentTarget?: ContainerID;\n events: LoroEvent[];\n}\n\n/**\n * The concrete event of Loro.\n */\nexport interface LoroEvent {\n /**\n * The container ID of the event's target.\n */\n target: ContainerID;\n diff: Diff;\n /**\n * The absolute path of the event's emitter, which can be an index of a list container or a key of a map container.\n */\n path: Path;\n}\n\nexport type ListDiff = {\n type: \"list\";\n diff: Delta<(Value | Container)[]>[];\n};\n\nexport type TextDiff = {\n type: \"text\";\n diff: Delta<string>[];\n};\n\nexport type MapDiff = {\n type: \"map\";\n updated: Record<string, Value | Container | undefined>;\n};\n\nexport type TreeDiffItem =\n | {\n target: TreeID;\n action: \"create\";\n parent: TreeID | undefined;\n index: number;\n position: string;\n }\n | { target: TreeID; action: \"delete\" }\n | {\n target: TreeID;\n action: \"move\";\n parent: TreeID | undefined;\n index: number;\n position: string;\n };\n\nexport type TreeDiff = {\n type: \"tree\";\n diff: TreeDiffItem[];\n};\n\nexport type CounterDiff = {\n type: \"counter\";\n increment: number;\n}\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff | CounterDiff;\n\ninterface Listener {\n (event: LoroEventBatch): void;\n}\n\nconst CONTAINER_TYPES = [\"Map\", \"Text\", \"List\", \"Tree\", \"MovableList\", \"Counter\"];\n\nexport function isContainerId(s: string): s is ContainerID {\n return s.startsWith(\"cid:\");\n}\n\nexport { Loro };\n\n/** Whether the value is a container.\n *\n * # Example\n *\n * ```ts\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * const list = doc.getList(\"list\");\n * const text = doc.getText(\"text\");\n * isContainer(map); // true\n * isContainer(list); // true\n * isContainer(text); // true\n * isContainer(123); // false\n * isContainer(\"123\"); // false\n * isContainer({}); // false\n */\nexport function isContainer(value: any): value is Container {\n if (typeof value !== \"object\" || value == null) {\n return false;\n }\n\n const p = Object.getPrototypeOf(value);\n if (p == null || typeof p !== \"object\" || typeof p[\"kind\"] !== \"function\") {\n return false;\n }\n\n return CONTAINER_TYPES.includes(value.kind());\n}\n\n/** Get the type of a value that may be a container.\n *\n * # Example\n *\n * ```ts\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * const list = doc.getList(\"list\");\n * const text = doc.getText(\"text\");\n * getType(map); // \"Map\"\n * getType(list); // \"List\"\n * getType(text); // \"Text\"\n * getType(123); // \"Json\"\n * getType(\"123\"); // \"Json\"\n * getType({}); // \"Json\"\n * ```\n */\nexport function getType<T>(\n value: T,\n): T extends LoroText\n ? \"Text\"\n : T extends LoroMap<any>\n ? \"Map\"\n : T extends LoroTree<any>\n ? \"Tree\"\n : T extends LoroList<any>\n ? \"List\"\n :T extends LoroCounter?\"Counter\"\n : \"Json\" {\n if (isContainer(value)) {\n return value.kind() as unknown as any;\n }\n\n return \"Json\" as any;\n}\n\ndeclare module \"loro-wasm\" {\n interface Loro {\n subscribe(listener: Listener): number;\n }\n\n interface UndoManager {\n /**\n * Set the callback function that is called when an undo/redo step is pushed.\n * The function can return a meta data value that will be attached to the given stack item.\n *\n * @param listener - The callback function.\n */\n setOnPush(listener?: UndoConfig[\"onPush\"]): void;\n /**\n * Set the callback function that is called when an undo/redo step is popped.\n * The function will have a meta data value that was attached to the given stack item when `onPush` was called.\n *\n * @param listener - The callback function.\n */\n setOnPop(listener?: UndoConfig[\"onPop\"]): void;\n }\n\n interface Loro<\n T extends Record<string, Container> = Record<string, Container>,\n > {\n /**\n * Get a LoroMap by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * ```\n */\n getMap<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroMap ? T[Key] : LoroMap;\n /**\n * Get a LoroList by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * ```\n */\n getList<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroList ? T[Key] : LoroList;\n /**\n * Get a LoroMovableList by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * ```\n */\n getMovableList<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroMovableList ? T[Key] : LoroMovableList;\n /**\n * Get a LoroTree by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const tree = doc.getTree(\"tree\");\n * ```\n */\n getTree<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroTree ? T[Key] : LoroTree;\n getText(key: string | ContainerID): LoroText;\n }\n\n interface LoroList<T = unknown> {\n new (): LoroList<T>;\n /**\n * Get elements of the list. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.insertContainer(3, new LoroText());\n * console.log(list.value); // [100, \"foo\", true, LoroText];\n * ```\n */\n toArray(): T[];\n /**\n * Insert a container at the index.\n *\n * @example\n * ```ts\n * import { Loro, LoroText } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * const text = list.insertContainer(1, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [100, \"Hello\"];\n * ```\n */\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n /**\n * Get the value at the index. If the value is a container, the corresponding handler will be returned.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * console.log(list.get(0)); // 100\n * console.log(list.get(1)); // undefined\n * ```\n */\n get(index: number): T;\n /**\n * Insert a value at index.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * console.log(list.value); // [100, \"foo\", true];\n * ```\n */\n insert<V extends T>(pos: number, value: Exclude<V, Container>): void;\n delete(pos: number, len: number): void;\n push<V extends T>(value: Exclude<V, Container>): void;\n subscribe(listener: Listener): number;\n getAttached(): undefined | LoroList<T>;\n }\n\n interface LoroMovableList<T = unknown> {\n new (): LoroMovableList<T>;\n /**\n * Get elements of the list. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * @example\n * ```ts\n * import { Loro, LoroText } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.insertContainer(3, new LoroText());\n * console.log(list.value); // [100, \"foo\", true, LoroText];\n * ```\n */\n toArray(): T[];\n /**\n * Insert a container at the index.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * const text = list.insertContainer(1, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [100, \"Hello\"];\n * ```\n */\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n /**\n * Get the value at the index. If the value is a container, the corresponding handler will be returned.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMoableList(\"list\");\n * list.insert(0, 100);\n * console.log(list.get(0)); // 100\n * console.log(list.get(1)); // undefined\n * ```\n */\n get(index: number): T;\n /**\n * Insert a value at index.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * console.log(list.value); // [100, \"foo\", true];\n * ```\n */\n insert<V extends T>(pos: number, value: Exclude<V, Container>): void;\n delete(pos: number, len: number): void;\n push<V extends T>(value: Exclude<V, Container>): void;\n subscribe(listener: Listener): number;\n getAttached(): undefined | LoroMovableList<T>;\n /**\n * Set the value at the given position.\n *\n * It's different from `delete` + `insert` that it will replace the value at the position.\n *\n * For example, if you have a list `[1, 2, 3]`, and you call `set(1, 100)`, the list will be `[1, 100, 3]`.\n * If concurrently someone call `set(1, 200)`, the list will be `[1, 200, 3]` or `[1, 100, 3]`.\n *\n * But if you use `delete` + `insert` to simulate the set operation, they may create redundant operations\n * and the final result will be `[1, 100, 200, 3]` or `[1, 200, 100, 3]`.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.set(1, \"bar\");\n * console.log(list.value); // [100, \"bar\", true];\n * ```\n */\n set<V extends T>(pos: number, value: Exclude<V, Container>): void;\n /**\n * Set a container at the index.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * const text = list.setContainer(0, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [\"Hello\"];\n * ```\n */\n setContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n }\n\n interface LoroMap<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n new (): LoroMap<T>;\n /**\n * Get the value of the key. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * The object returned is a new js object each time because it need to cross\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const bar = map.get(\"foo\");\n * ```\n */\n getOrCreateContainer<C extends Container>(key: string, child: C): C;\n /**\n * Set the key with a container.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const text = map.setContainer(\"text\", new LoroText());\n * const list = map.setContainer(\"list\", new LoroText());\n * ```\n */\n setContainer<C extends Container, Key extends keyof T>(\n key: Key,\n child: C,\n ): NonNullableType<T[Key]> extends C ? NonNullableType<T[Key]> : C;\n /**\n * Get the value of the key. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * The object/value returned is a new js object/value each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const bar = map.get(\"foo\");\n * ```\n */\n get<Key extends keyof T>(key: Key): T[Key];\n /**\n * Set the key with the value.\n *\n * If the value of the key is exist, the old value will be updated.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * map.set(\"foo\", \"baz\");\n * ```\n */\n set<Key extends keyof T, V extends T[Key]>(\n key: Key,\n value: Exclude<V, Container>,\n ): void;\n delete(key: string): void;\n subscribe(listener: Listener): number;\n }\n\n interface LoroText {\n new (): LoroText;\n insert(pos: number, text: string): void;\n delete(pos: number, len: number): void;\n subscribe(listener: Listener): number;\n }\n\n interface LoroTree<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n new (): LoroTree<T>;\n /**\n * Create a new tree node as the child of parent and return a `LoroTreeNode` instance.\n * If the parent is undefined, the tree node will be a root node.\n *\n * If the index is not provided, the new node will be appended to the end.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const tree = doc.getTree(\"tree\");\n * const root = tree.createNode();\n * const node = tree.createNode(undefined, 0);\n *\n * // undefined\n * // / \\\n * // node root\n * ```\n */\n createNode(parent?: TreeID, index?: number): LoroTreeNode<T>;\n move(target: TreeID, parent?: TreeID, index?: number): void;\n delete(target: TreeID): void;\n has(target: TreeID): boolean;\n /**\n * Get LoroTreeNode by the TreeID.\n */\n getNodeByID(target: TreeID): LoroTreeNode<T>;\n subscribe(listener: Listener): number;\n }\n\n interface LoroTreeNode<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n /**\n * Get the associated metadata map container of a tree node.\n */\n readonly data: LoroMap<T>;\n /** \n * Create a new node as the child of the current node and\n * return an instance of `LoroTreeNode`.\n *\n * If the index is not provided, the new node will be appended to the end.\n *\n * @example\n * ```typescript\n * import { Loro } from \"loro-crdt\";\n *\n * let doc = new Loro();\n * let tree = doc.getTree(\"tree\");\n * let root = tree.createNode();\n * let node = root.createNode();\n * let node2 = root.createNode(0);\n * // root\n * // / \\\n * // node2 node\n * ```\n */ \n createNode(index?: number): LoroTreeNode<T>;\n move(parent?: LoroTreeNode<T>, index?: number): void;\n parent(): LoroTreeNode<T> | undefined;\n /**\n * Get the children of this node.\n *\n * The objects returned are new js objects each time because they need to cross\n * the WASM boundary.\n */\n children(): Array<LoroTreeNode<T>> | undefined;\n }\n\n interface AwarenessWasm<T extends Value = Value> {\n getState(peer: PeerID): T | undefined;\n getTimestamp(peer: PeerID): number | undefined;\n getAllStates(): Record<PeerID, T>;\n setLocalState(value: T): void;\n removeOutdated(): PeerID[];\n }\n}\n\ntype NonNullableType<T> = Exclude<T, null | undefined>;\n"],"names":["AwarenessWasm"],"mappings":"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"}
1
+ {"version":3,"file":"loro.js","sources":["../src/awareness.ts","../src/index.ts"],"sourcesContent":["import { AwarenessWasm, PeerID, Value } from \"loro-wasm\";\n\nexport type AwarenessListener = (\n arg: { updated: PeerID[]; added: PeerID[]; removed: PeerID[] },\n origin: \"local\" | \"timeout\" | \"remote\" | string,\n) => void;\n\n/**\n * Awareness is a structure that allows to track the ephemeral state of the peers.\n *\n * If we don't receive a state update from a peer within the timeout, we will remove their state.\n * The timeout is in milliseconds. This can be used to handle the off-line state of a peer.\n */\nexport class Awareness<T extends Value = Value> {\n inner: AwarenessWasm<T>;\n private peer: PeerID;\n private timer: number | undefined;\n private timeout: number;\n private listeners: Set<AwarenessListener> = new Set();\n constructor(peer: PeerID, timeout: number = 30000) {\n this.inner = new AwarenessWasm(peer, timeout);\n this.peer = peer;\n this.timeout = timeout;\n }\n\n apply(bytes: Uint8Array, origin = \"remote\") {\n const { updated, added } = this.inner.apply(bytes);\n this.listeners.forEach((listener) => {\n listener({ updated, added, removed: [] }, origin);\n });\n\n this.startTimerIfNotEmpty();\n }\n\n setLocalState(state: T) {\n const wasEmpty = this.inner.getState(this.peer) == null;\n this.inner.setLocalState(state);\n if (wasEmpty) {\n this.listeners.forEach((listener) => {\n listener(\n { updated: [], added: [this.inner.peer()], removed: [] },\n \"local\",\n );\n });\n } else {\n this.listeners.forEach((listener) => {\n listener(\n { updated: [this.inner.peer()], added: [], removed: [] },\n \"local\",\n );\n });\n }\n\n this.startTimerIfNotEmpty();\n }\n\n getLocalState(): T | undefined {\n return this.inner.getState(this.peer);\n }\n\n getAllStates(): Record<PeerID, T> {\n return this.inner.getAllStates();\n }\n\n encode(peers: PeerID[]): Uint8Array {\n return this.inner.encode(peers);\n }\n\n encodeAll(): Uint8Array {\n return this.inner.encodeAll();\n }\n\n addListener(listener: AwarenessListener) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: AwarenessListener) {\n this.listeners.delete(listener);\n }\n\n peers(): PeerID[] {\n return this.inner.peers();\n }\n\n destroy() {\n clearInterval(this.timer);\n this.listeners.clear();\n }\n\n private startTimerIfNotEmpty() {\n if (this.inner.isEmpty() || this.timer != null) {\n return;\n }\n\n this.timer = setInterval(() => {\n const removed = this.inner.removeOutdated();\n if (removed.length > 0) {\n this.listeners.forEach((listener) => {\n listener({ updated: [], added: [], removed }, \"timeout\");\n });\n }\n if (this.inner.isEmpty()) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n }, this.timeout / 2) as unknown as number;\n }\n}\n","export {\n AwarenessWasm, Change, Container, ContainerID, ContainerType,\n Cursor, Delta, ExportMode, ImportBlobMetadata,\n JsonChange, JsonContainerID, JsonOp, JsonOpID, JsonSchema,\n JsonValue, ListOp, LoroCounter, LoroList, LoroMap, LoroDoc,\n LoroMovableList, LoroText, LoroTree, LoroTreeNode, MapOp, MovableListOp,\n OpId, PeerID, Side, TextOp, TreeID, TreeNodeValue, TreeOp, UndoConfig,\n UndoManager, UnknownOp, Value, VersionVector, decodeImportBlobMeta, setDebug,\n newContainerID, newRootContainerID\n} from \"loro-wasm\";\nimport {\n Container,\n ContainerID,\n Delta,\n LoroDoc,\n LoroList,\n LoroMap,\n LoroText,\n LoroTree,\n LoroCounter,\n OpId,\n TreeID,\n Value,\n} from \"loro-wasm\";\n\n/**\n * @deprecated Please use LoroDoc\n */\nexport class Loro extends LoroDoc { }\nexport { Awareness } from \"./awareness\";\n\nexport type Frontiers = OpId[];\n\n/**\n * Represents a path to identify the exact location of an event's target.\n * The path is composed of numbers (e.g., indices of a list container) strings\n * (e.g., keys of a map container) and TreeID (the node of a tree container),\n * indicating the absolute position of the event's source within a loro document.\n */\nexport type Path = (number | string | TreeID)[];\n\n/**\n * A batch of events that created by a single `import`/`transaction`/`checkout`.\n *\n * @prop by - How the event is triggered.\n * @prop origin - (Optional) Provides information about the origin of the event.\n * @prop diff - Contains the differential information related to the event.\n * @prop target - Identifies the container ID of the event's target.\n * @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.\n */\nexport interface LoroEventBatch {\n /**\n * How the event is triggered.\n *\n * - `local`: The event is triggered by a local transaction.\n * - `import`: The event is triggered by an import operation.\n * - `checkout`: The event is triggered by a checkout operation.\n */\n by: \"local\" | \"import\" | \"checkout\";\n origin?: string;\n /**\n * The container ID of the current event receiver.\n * It's undefined if the subscriber is on the root document.\n */\n currentTarget?: ContainerID;\n events: LoroEvent[];\n}\n\n/**\n * The concrete event of Loro.\n */\nexport interface LoroEvent {\n /**\n * The container ID of the event's target.\n */\n target: ContainerID;\n diff: Diff;\n /**\n * The absolute path of the event's emitter, which can be an index of a list container or a key of a map container.\n */\n path: Path;\n}\n\nexport type ListDiff = {\n type: \"list\";\n diff: Delta<(Value | Container)[]>[];\n};\n\nexport type TextDiff = {\n type: \"text\";\n diff: Delta<string>[];\n};\n\nexport type MapDiff = {\n type: \"map\";\n updated: Record<string, Value | Container | undefined>;\n};\n\nexport type TreeDiffItem =\n | {\n target: TreeID;\n action: \"create\";\n parent: TreeID | undefined;\n index: number;\n fractional_index: string;\n }\n | { target: TreeID; action: \"delete\"; old_parent: TreeID | undefined; old_index: number }\n | {\n target: TreeID;\n action: \"move\";\n parent: TreeID | undefined;\n index: number;\n fractional_index: string;\n old_parent: TreeID | undefined;\n old_index: number;\n };\n\nexport type TreeDiff = {\n type: \"tree\";\n diff: TreeDiffItem[];\n};\n\nexport type CounterDiff = {\n type: \"counter\";\n increment: number;\n}\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff | CounterDiff;\n\ninterface Listener {\n (event: LoroEventBatch): void;\n}\n\nconst CONTAINER_TYPES = [\"Map\", \"Text\", \"List\", \"Tree\", \"MovableList\", \"Counter\"];\n\nexport function isContainerId(s: string): s is ContainerID {\n return s.startsWith(\"cid:\");\n}\n\n/** Whether the value is a container.\n *\n * # Example\n *\n * ```ts\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * const list = doc.getList(\"list\");\n * const text = doc.getText(\"text\");\n * isContainer(map); // true\n * isContainer(list); // true\n * isContainer(text); // true\n * isContainer(123); // false\n * isContainer(\"123\"); // false\n * isContainer({}); // false\n */\nexport function isContainer(value: any): value is Container {\n if (typeof value !== \"object\" || value == null) {\n return false;\n }\n\n const p = Object.getPrototypeOf(value);\n if (p == null || typeof p !== \"object\" || typeof p[\"kind\"] !== \"function\") {\n return false;\n }\n\n return CONTAINER_TYPES.includes(value.kind());\n}\n\n/** Get the type of a value that may be a container.\n *\n * # Example\n *\n * ```ts\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * const list = doc.getList(\"list\");\n * const text = doc.getText(\"text\");\n * getType(map); // \"Map\"\n * getType(list); // \"List\"\n * getType(text); // \"Text\"\n * getType(123); // \"Json\"\n * getType(\"123\"); // \"Json\"\n * getType({}); // \"Json\"\n * ```\n */\nexport function getType<T>(\n value: T,\n): T extends LoroText\n ? \"Text\"\n : T extends LoroMap<any>\n ? \"Map\"\n : T extends LoroTree<any>\n ? \"Tree\"\n : T extends LoroList<any>\n ? \"List\"\n : T extends LoroCounter ? \"Counter\"\n : \"Json\" {\n if (isContainer(value)) {\n return value.kind() as unknown as any;\n }\n\n return \"Json\" as any;\n}\n\ndeclare module \"loro-wasm\" {\n interface LoroDoc {\n subscribe(listener: Listener): number;\n }\n\n interface UndoManager {\n /**\n * Set the callback function that is called when an undo/redo step is pushed.\n * The function can return a meta data value that will be attached to the given stack item.\n *\n * @param listener - The callback function.\n */\n setOnPush(listener?: UndoConfig[\"onPush\"]): void;\n /**\n * Set the callback function that is called when an undo/redo step is popped.\n * The function will have a meta data value that was attached to the given stack item when `onPush` was called.\n *\n * @param listener - The callback function.\n */\n setOnPop(listener?: UndoConfig[\"onPop\"]): void;\n }\n\n interface LoroDoc<\n T extends Record<string, Container> = Record<string, Container>,\n > {\n /**\n * Get a LoroMap by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * ```\n */\n getMap<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroMap ? T[Key] : LoroMap;\n /**\n * Get a LoroList by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * ```\n */\n getList<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroList ? T[Key] : LoroList;\n /**\n * Get a LoroMovableList by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * ```\n */\n getMovableList<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroMovableList ? T[Key] : LoroMovableList;\n /**\n * Get a LoroTree by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const tree = doc.getTree(\"tree\");\n * ```\n */\n getTree<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroTree ? T[Key] : LoroTree;\n getText(key: string | ContainerID): LoroText;\n }\n\n interface LoroList<T = unknown> {\n new(): LoroList<T>;\n /**\n * Get elements of the list. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.insertContainer(3, new LoroText());\n * console.log(list.value); // [100, \"foo\", true, LoroText];\n * ```\n */\n toArray(): T[];\n /**\n * Insert a container at the index.\n *\n * @example\n * ```ts\n * import { LoroDoc, LoroText } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * const text = list.insertContainer(1, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [100, \"Hello\"];\n * ```\n */\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n /**\n * Get the value at the index. If the value is a container, the corresponding handler will be returned.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * console.log(list.get(0)); // 100\n * console.log(list.get(1)); // undefined\n * ```\n */\n get(index: number): T;\n /**\n * Insert a value at index.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * console.log(list.value); // [100, \"foo\", true];\n * ```\n */\n insert<V extends T>(pos: number, value: Exclude<V, Container>): void;\n delete(pos: number, len: number): void;\n push<V extends T>(value: Exclude<V, Container>): void;\n subscribe(listener: Listener): number;\n getAttached(): undefined | LoroList<T>;\n }\n\n interface LoroMovableList<T = unknown> {\n new(): LoroMovableList<T>;\n /**\n * Get elements of the list. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * @example\n * ```ts\n * import { LoroDoc, LoroText } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.insertContainer(3, new LoroText());\n * console.log(list.value); // [100, \"foo\", true, LoroText];\n * ```\n */\n toArray(): T[];\n /**\n * Insert a container at the index.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * const text = list.insertContainer(1, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [100, \"Hello\"];\n * ```\n */\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n /**\n * Get the value at the index. If the value is a container, the corresponding handler will be returned.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * console.log(list.get(0)); // 100\n * console.log(list.get(1)); // undefined\n * ```\n */\n get(index: number): T;\n /**\n * Insert a value at index.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * console.log(list.value); // [100, \"foo\", true];\n * ```\n */\n insert<V extends T>(pos: number, value: Exclude<V, Container>): void;\n delete(pos: number, len: number): void;\n push<V extends T>(value: Exclude<V, Container>): void;\n subscribe(listener: Listener): number;\n getAttached(): undefined | LoroMovableList<T>;\n /**\n * Set the value at the given position.\n *\n * It's different from `delete` + `insert` that it will replace the value at the position.\n *\n * For example, if you have a list `[1, 2, 3]`, and you call `set(1, 100)`, the list will be `[1, 100, 3]`.\n * If concurrently someone call `set(1, 200)`, the list will be `[1, 200, 3]` or `[1, 100, 3]`.\n *\n * But if you use `delete` + `insert` to simulate the set operation, they may create redundant operations\n * and the final result will be `[1, 100, 200, 3]` or `[1, 200, 100, 3]`.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.set(1, \"bar\");\n * console.log(list.value); // [100, \"bar\", true];\n * ```\n */\n set<V extends T>(pos: number, value: Exclude<V, Container>): void;\n /**\n * Set a container at the index.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * const text = list.setContainer(0, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [\"Hello\"];\n * ```\n */\n setContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n }\n\n interface LoroMap<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n new(): LoroMap<T>;\n /**\n * Get the value of the key. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * The object returned is a new js object each time because it need to cross\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const bar = map.get(\"foo\");\n * ```\n */\n getOrCreateContainer<C extends Container>(key: string, child: C): C;\n /**\n * Set the key with a container.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const text = map.setContainer(\"text\", new LoroText());\n * const list = map.setContainer(\"list\", new LoroText());\n * ```\n */\n setContainer<C extends Container, Key extends keyof T>(\n key: Key,\n child: C,\n ): NonNullableType<T[Key]> extends C ? NonNullableType<T[Key]> : C;\n /**\n * Get the value of the key. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * The object/value returned is a new js object/value each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const bar = map.get(\"foo\");\n * ```\n */\n get<Key extends keyof T>(key: Key): T[Key];\n /**\n * Set the key with the value.\n *\n * If the value of the key is exist, the old value will be updated.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * map.set(\"foo\", \"baz\");\n * ```\n */\n set<Key extends keyof T, V extends T[Key]>(\n key: Key,\n value: Exclude<V, Container>,\n ): void;\n delete(key: string): void;\n subscribe(listener: Listener): number;\n }\n\n interface LoroText {\n new(): LoroText;\n insert(pos: number, text: string): void;\n delete(pos: number, len: number): void;\n subscribe(listener: Listener): number;\n }\n\n interface LoroTree<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n new(): LoroTree<T>;\n /**\n * Create a new tree node as the child of parent and return a `LoroTreeNode` instance.\n * If the parent is undefined, the tree node will be a root node.\n *\n * If the index is not provided, the new node will be appended to the end.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const tree = doc.getTree(\"tree\");\n * const root = tree.createNode();\n * const node = tree.createNode(undefined, 0);\n *\n * // undefined\n * // / \\\n * // node root\n * ```\n */\n createNode(parent?: TreeID, index?: number): LoroTreeNode<T>;\n move(target: TreeID, parent?: TreeID, index?: number): void;\n delete(target: TreeID): void;\n has(target: TreeID): boolean;\n /**\n * Get LoroTreeNode by the TreeID.\n */\n getNodeByID(target: TreeID): LoroTreeNode<T>;\n subscribe(listener: Listener): number;\n }\n\n interface LoroTreeNode<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n /**\n * Get the associated metadata map container of a tree node.\n */\n readonly data: LoroMap<T>;\n /** \n * Create a new node as the child of the current node and\n * return an instance of `LoroTreeNode`.\n *\n * If the index is not provided, the new node will be appended to the end.\n *\n * @example\n * ```typescript\n * import { LoroDoc } from \"loro-crdt\";\n *\n * let doc = new LoroDoc();\n * let tree = doc.getTree(\"tree\");\n * let root = tree.createNode();\n * let node = root.createNode();\n * let node2 = root.createNode(0);\n * // root\n * // / \\\n * // node2 node\n * ```\n */\n createNode(index?: number): LoroTreeNode<T>;\n move(parent?: LoroTreeNode<T>, index?: number): void;\n parent(): LoroTreeNode<T> | undefined;\n /**\n * Get the children of this node.\n *\n * The objects returned are new js objects each time because they need to cross\n * the WASM boundary.\n */\n children(): Array<LoroTreeNode<T>> | undefined;\n }\n\n interface AwarenessWasm<T extends Value = Value> {\n getState(peer: PeerID): T | undefined;\n getTimestamp(peer: PeerID): number | undefined;\n getAllStates(): Record<PeerID, T>;\n setLocalState(value: T): void;\n removeOutdated(): PeerID[];\n }\n}\n\ntype NonNullableType<T> = Exclude<T, null | undefined>;\n"],"names":["AwarenessWasm","LoroDoc"],"mappings":"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"}
package/dist/loro.mjs CHANGED
@@ -1,6 +1,5 @@
1
- import { AwarenessWasm } from 'loro-wasm';
2
- export * from 'loro-wasm';
3
- export { Loro } from 'loro-wasm';
1
+ import { AwarenessWasm, LoroDoc } from 'loro-wasm';
2
+ export { AwarenessWasm, Change, Container, ContainerID, ContainerType, Cursor, Delta, ExportMode, ImportBlobMetadata, JsonChange, JsonContainerID, JsonOp, JsonOpID, JsonSchema, JsonValue, ListOp, LoroCounter, LoroDoc, LoroList, LoroMap, LoroMovableList, LoroText, LoroTree, LoroTreeNode, MapOp, MovableListOp, OpId, PeerID, Side, TextOp, TreeID, TreeNodeValue, TreeOp, UndoConfig, UndoManager, UnknownOp, Value, VersionVector, decodeImportBlobMeta, newContainerID, newRootContainerID, setDebug } from 'loro-wasm';
4
3
 
5
4
  class Awareness {
6
5
  inner;
@@ -84,6 +83,8 @@ class Awareness {
84
83
  }
85
84
  }
86
85
 
86
+ class Loro extends LoroDoc {
87
+ }
87
88
  const CONTAINER_TYPES = ["Map", "Text", "List", "Tree", "MovableList", "Counter"];
88
89
  function isContainerId(s) {
89
90
  return s.startsWith("cid:");
@@ -105,5 +106,5 @@ function getType(value) {
105
106
  return "Json";
106
107
  }
107
108
 
108
- export { Awareness, getType, isContainer, isContainerId };
109
+ export { Awareness, Loro, getType, isContainer, isContainerId };
109
110
  //# sourceMappingURL=loro.mjs.map
package/dist/loro.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"loro.mjs","sources":["../src/awareness.ts","../src/index.ts"],"sourcesContent":["import { AwarenessWasm, PeerID, Value } from \"loro-wasm\";\n\nexport type AwarenessListener = (\n arg: { updated: PeerID[]; added: PeerID[]; removed: PeerID[] },\n origin: \"local\" | \"timeout\" | \"remote\" | string,\n) => void;\n\n/**\n * Awareness is a structure that allows to track the ephemeral state of the peers.\n *\n * If we don't receive a state update from a peer within the timeout, we will remove their state.\n * The timeout is in milliseconds. This can be used to handle the off-line state of a peer.\n */\nexport class Awareness<T extends Value = Value> {\n inner: AwarenessWasm<T>;\n private peer: PeerID;\n private timer: number | undefined;\n private timeout: number;\n private listeners: Set<AwarenessListener> = new Set();\n constructor(peer: PeerID, timeout: number = 30000) {\n this.inner = new AwarenessWasm(peer, timeout);\n this.peer = peer;\n this.timeout = timeout;\n }\n\n apply(bytes: Uint8Array, origin = \"remote\") {\n const { updated, added } = this.inner.apply(bytes);\n this.listeners.forEach((listener) => {\n listener({ updated, added, removed: [] }, origin);\n });\n\n this.startTimerIfNotEmpty();\n }\n\n setLocalState(state: T) {\n const wasEmpty = this.inner.getState(this.peer) == null;\n this.inner.setLocalState(state);\n if (wasEmpty) {\n this.listeners.forEach((listener) => {\n listener(\n { updated: [], added: [this.inner.peer()], removed: [] },\n \"local\",\n );\n });\n } else {\n this.listeners.forEach((listener) => {\n listener(\n { updated: [this.inner.peer()], added: [], removed: [] },\n \"local\",\n );\n });\n }\n\n this.startTimerIfNotEmpty();\n }\n\n getLocalState(): T | undefined {\n return this.inner.getState(this.peer);\n }\n\n getAllStates(): Record<PeerID, T> {\n return this.inner.getAllStates();\n }\n\n encode(peers: PeerID[]): Uint8Array {\n return this.inner.encode(peers);\n }\n\n encodeAll(): Uint8Array {\n return this.inner.encodeAll();\n }\n\n addListener(listener: AwarenessListener) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: AwarenessListener) {\n this.listeners.delete(listener);\n }\n\n peers(): PeerID[] {\n return this.inner.peers();\n }\n\n destroy() {\n clearInterval(this.timer);\n this.listeners.clear();\n }\n\n private startTimerIfNotEmpty() {\n if (this.inner.isEmpty() || this.timer != null) {\n return;\n }\n\n this.timer = setInterval(() => {\n const removed = this.inner.removeOutdated();\n if (removed.length > 0) {\n this.listeners.forEach((listener) => {\n listener({ updated: [], added: [], removed }, \"timeout\");\n });\n }\n if (this.inner.isEmpty()) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n }, this.timeout / 2) as unknown as number;\n }\n}\n","export * from \"loro-wasm\";\nimport {\n Container,\n ContainerID,\n Delta,\n Loro,\n LoroList,\n LoroMap,\n LoroText,\n LoroTree,\n LoroCounter,\n OpId,\n TreeID,\n Value,\n} from \"loro-wasm\";\nexport { Awareness } from \"./awareness\";\n\nexport type Frontiers = OpId[];\n\n/**\n * Represents a path to identify the exact location of an event's target.\n * The path is composed of numbers (e.g., indices of a list container) strings\n * (e.g., keys of a map container) and TreeID (the node of a tree container),\n * indicating the absolute position of the event's source within a loro document.\n */\nexport type Path = (number | string | TreeID)[];\n\n/**\n * A batch of events that created by a single `import`/`transaction`/`checkout`.\n *\n * @prop by - How the event is triggered.\n * @prop origin - (Optional) Provides information about the origin of the event.\n * @prop diff - Contains the differential information related to the event.\n * @prop target - Identifies the container ID of the event's target.\n * @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.\n */\nexport interface LoroEventBatch {\n /**\n * How the event is triggered.\n *\n * - `local`: The event is triggered by a local transaction.\n * - `import`: The event is triggered by an import operation.\n * - `checkout`: The event is triggered by a checkout operation.\n */\n by: \"local\" | \"import\" | \"checkout\";\n origin?: string;\n /**\n * The container ID of the current event receiver.\n * It's undefined if the subscriber is on the root document.\n */\n currentTarget?: ContainerID;\n events: LoroEvent[];\n}\n\n/**\n * The concrete event of Loro.\n */\nexport interface LoroEvent {\n /**\n * The container ID of the event's target.\n */\n target: ContainerID;\n diff: Diff;\n /**\n * The absolute path of the event's emitter, which can be an index of a list container or a key of a map container.\n */\n path: Path;\n}\n\nexport type ListDiff = {\n type: \"list\";\n diff: Delta<(Value | Container)[]>[];\n};\n\nexport type TextDiff = {\n type: \"text\";\n diff: Delta<string>[];\n};\n\nexport type MapDiff = {\n type: \"map\";\n updated: Record<string, Value | Container | undefined>;\n};\n\nexport type TreeDiffItem =\n | {\n target: TreeID;\n action: \"create\";\n parent: TreeID | undefined;\n index: number;\n position: string;\n }\n | { target: TreeID; action: \"delete\" }\n | {\n target: TreeID;\n action: \"move\";\n parent: TreeID | undefined;\n index: number;\n position: string;\n };\n\nexport type TreeDiff = {\n type: \"tree\";\n diff: TreeDiffItem[];\n};\n\nexport type CounterDiff = {\n type: \"counter\";\n increment: number;\n}\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff | CounterDiff;\n\ninterface Listener {\n (event: LoroEventBatch): void;\n}\n\nconst CONTAINER_TYPES = [\"Map\", \"Text\", \"List\", \"Tree\", \"MovableList\", \"Counter\"];\n\nexport function isContainerId(s: string): s is ContainerID {\n return s.startsWith(\"cid:\");\n}\n\nexport { Loro };\n\n/** Whether the value is a container.\n *\n * # Example\n *\n * ```ts\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * const list = doc.getList(\"list\");\n * const text = doc.getText(\"text\");\n * isContainer(map); // true\n * isContainer(list); // true\n * isContainer(text); // true\n * isContainer(123); // false\n * isContainer(\"123\"); // false\n * isContainer({}); // false\n */\nexport function isContainer(value: any): value is Container {\n if (typeof value !== \"object\" || value == null) {\n return false;\n }\n\n const p = Object.getPrototypeOf(value);\n if (p == null || typeof p !== \"object\" || typeof p[\"kind\"] !== \"function\") {\n return false;\n }\n\n return CONTAINER_TYPES.includes(value.kind());\n}\n\n/** Get the type of a value that may be a container.\n *\n * # Example\n *\n * ```ts\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * const list = doc.getList(\"list\");\n * const text = doc.getText(\"text\");\n * getType(map); // \"Map\"\n * getType(list); // \"List\"\n * getType(text); // \"Text\"\n * getType(123); // \"Json\"\n * getType(\"123\"); // \"Json\"\n * getType({}); // \"Json\"\n * ```\n */\nexport function getType<T>(\n value: T,\n): T extends LoroText\n ? \"Text\"\n : T extends LoroMap<any>\n ? \"Map\"\n : T extends LoroTree<any>\n ? \"Tree\"\n : T extends LoroList<any>\n ? \"List\"\n :T extends LoroCounter?\"Counter\"\n : \"Json\" {\n if (isContainer(value)) {\n return value.kind() as unknown as any;\n }\n\n return \"Json\" as any;\n}\n\ndeclare module \"loro-wasm\" {\n interface Loro {\n subscribe(listener: Listener): number;\n }\n\n interface UndoManager {\n /**\n * Set the callback function that is called when an undo/redo step is pushed.\n * The function can return a meta data value that will be attached to the given stack item.\n *\n * @param listener - The callback function.\n */\n setOnPush(listener?: UndoConfig[\"onPush\"]): void;\n /**\n * Set the callback function that is called when an undo/redo step is popped.\n * The function will have a meta data value that was attached to the given stack item when `onPush` was called.\n *\n * @param listener - The callback function.\n */\n setOnPop(listener?: UndoConfig[\"onPop\"]): void;\n }\n\n interface Loro<\n T extends Record<string, Container> = Record<string, Container>,\n > {\n /**\n * Get a LoroMap by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * ```\n */\n getMap<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroMap ? T[Key] : LoroMap;\n /**\n * Get a LoroList by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * ```\n */\n getList<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroList ? T[Key] : LoroList;\n /**\n * Get a LoroMovableList by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * ```\n */\n getMovableList<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroMovableList ? T[Key] : LoroMovableList;\n /**\n * Get a LoroTree by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const tree = doc.getTree(\"tree\");\n * ```\n */\n getTree<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroTree ? T[Key] : LoroTree;\n getText(key: string | ContainerID): LoroText;\n }\n\n interface LoroList<T = unknown> {\n new (): LoroList<T>;\n /**\n * Get elements of the list. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.insertContainer(3, new LoroText());\n * console.log(list.value); // [100, \"foo\", true, LoroText];\n * ```\n */\n toArray(): T[];\n /**\n * Insert a container at the index.\n *\n * @example\n * ```ts\n * import { Loro, LoroText } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * const text = list.insertContainer(1, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [100, \"Hello\"];\n * ```\n */\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n /**\n * Get the value at the index. If the value is a container, the corresponding handler will be returned.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * console.log(list.get(0)); // 100\n * console.log(list.get(1)); // undefined\n * ```\n */\n get(index: number): T;\n /**\n * Insert a value at index.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * console.log(list.value); // [100, \"foo\", true];\n * ```\n */\n insert<V extends T>(pos: number, value: Exclude<V, Container>): void;\n delete(pos: number, len: number): void;\n push<V extends T>(value: Exclude<V, Container>): void;\n subscribe(listener: Listener): number;\n getAttached(): undefined | LoroList<T>;\n }\n\n interface LoroMovableList<T = unknown> {\n new (): LoroMovableList<T>;\n /**\n * Get elements of the list. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * @example\n * ```ts\n * import { Loro, LoroText } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.insertContainer(3, new LoroText());\n * console.log(list.value); // [100, \"foo\", true, LoroText];\n * ```\n */\n toArray(): T[];\n /**\n * Insert a container at the index.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * const text = list.insertContainer(1, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [100, \"Hello\"];\n * ```\n */\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n /**\n * Get the value at the index. If the value is a container, the corresponding handler will be returned.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMoableList(\"list\");\n * list.insert(0, 100);\n * console.log(list.get(0)); // 100\n * console.log(list.get(1)); // undefined\n * ```\n */\n get(index: number): T;\n /**\n * Insert a value at index.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * console.log(list.value); // [100, \"foo\", true];\n * ```\n */\n insert<V extends T>(pos: number, value: Exclude<V, Container>): void;\n delete(pos: number, len: number): void;\n push<V extends T>(value: Exclude<V, Container>): void;\n subscribe(listener: Listener): number;\n getAttached(): undefined | LoroMovableList<T>;\n /**\n * Set the value at the given position.\n *\n * It's different from `delete` + `insert` that it will replace the value at the position.\n *\n * For example, if you have a list `[1, 2, 3]`, and you call `set(1, 100)`, the list will be `[1, 100, 3]`.\n * If concurrently someone call `set(1, 200)`, the list will be `[1, 200, 3]` or `[1, 100, 3]`.\n *\n * But if you use `delete` + `insert` to simulate the set operation, they may create redundant operations\n * and the final result will be `[1, 100, 200, 3]` or `[1, 200, 100, 3]`.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.set(1, \"bar\");\n * console.log(list.value); // [100, \"bar\", true];\n * ```\n */\n set<V extends T>(pos: number, value: Exclude<V, Container>): void;\n /**\n * Set a container at the index.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * const text = list.setContainer(0, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [\"Hello\"];\n * ```\n */\n setContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n }\n\n interface LoroMap<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n new (): LoroMap<T>;\n /**\n * Get the value of the key. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * The object returned is a new js object each time because it need to cross\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const bar = map.get(\"foo\");\n * ```\n */\n getOrCreateContainer<C extends Container>(key: string, child: C): C;\n /**\n * Set the key with a container.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const text = map.setContainer(\"text\", new LoroText());\n * const list = map.setContainer(\"list\", new LoroText());\n * ```\n */\n setContainer<C extends Container, Key extends keyof T>(\n key: Key,\n child: C,\n ): NonNullableType<T[Key]> extends C ? NonNullableType<T[Key]> : C;\n /**\n * Get the value of the key. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * The object/value returned is a new js object/value each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const bar = map.get(\"foo\");\n * ```\n */\n get<Key extends keyof T>(key: Key): T[Key];\n /**\n * Set the key with the value.\n *\n * If the value of the key is exist, the old value will be updated.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * map.set(\"foo\", \"baz\");\n * ```\n */\n set<Key extends keyof T, V extends T[Key]>(\n key: Key,\n value: Exclude<V, Container>,\n ): void;\n delete(key: string): void;\n subscribe(listener: Listener): number;\n }\n\n interface LoroText {\n new (): LoroText;\n insert(pos: number, text: string): void;\n delete(pos: number, len: number): void;\n subscribe(listener: Listener): number;\n }\n\n interface LoroTree<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n new (): LoroTree<T>;\n /**\n * Create a new tree node as the child of parent and return a `LoroTreeNode` instance.\n * If the parent is undefined, the tree node will be a root node.\n *\n * If the index is not provided, the new node will be appended to the end.\n *\n * @example\n * ```ts\n * import { Loro } from \"loro-crdt\";\n *\n * const doc = new Loro();\n * const tree = doc.getTree(\"tree\");\n * const root = tree.createNode();\n * const node = tree.createNode(undefined, 0);\n *\n * // undefined\n * // / \\\n * // node root\n * ```\n */\n createNode(parent?: TreeID, index?: number): LoroTreeNode<T>;\n move(target: TreeID, parent?: TreeID, index?: number): void;\n delete(target: TreeID): void;\n has(target: TreeID): boolean;\n /**\n * Get LoroTreeNode by the TreeID.\n */\n getNodeByID(target: TreeID): LoroTreeNode<T>;\n subscribe(listener: Listener): number;\n }\n\n interface LoroTreeNode<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n /**\n * Get the associated metadata map container of a tree node.\n */\n readonly data: LoroMap<T>;\n /** \n * Create a new node as the child of the current node and\n * return an instance of `LoroTreeNode`.\n *\n * If the index is not provided, the new node will be appended to the end.\n *\n * @example\n * ```typescript\n * import { Loro } from \"loro-crdt\";\n *\n * let doc = new Loro();\n * let tree = doc.getTree(\"tree\");\n * let root = tree.createNode();\n * let node = root.createNode();\n * let node2 = root.createNode(0);\n * // root\n * // / \\\n * // node2 node\n * ```\n */ \n createNode(index?: number): LoroTreeNode<T>;\n move(parent?: LoroTreeNode<T>, index?: number): void;\n parent(): LoroTreeNode<T> | undefined;\n /**\n * Get the children of this node.\n *\n * The objects returned are new js objects each time because they need to cross\n * the WASM boundary.\n */\n children(): Array<LoroTreeNode<T>> | undefined;\n }\n\n interface AwarenessWasm<T extends Value = Value> {\n getState(peer: PeerID): T | undefined;\n getTimestamp(peer: PeerID): number | undefined;\n getAllStates(): Record<PeerID, T>;\n setLocalState(value: T): void;\n removeOutdated(): PeerID[];\n }\n}\n\ntype NonNullableType<T> = Exclude<T, null | undefined>;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loro.mjs","sources":["../src/awareness.ts","../src/index.ts"],"sourcesContent":["import { AwarenessWasm, PeerID, Value } from \"loro-wasm\";\n\nexport type AwarenessListener = (\n arg: { updated: PeerID[]; added: PeerID[]; removed: PeerID[] },\n origin: \"local\" | \"timeout\" | \"remote\" | string,\n) => void;\n\n/**\n * Awareness is a structure that allows to track the ephemeral state of the peers.\n *\n * If we don't receive a state update from a peer within the timeout, we will remove their state.\n * The timeout is in milliseconds. This can be used to handle the off-line state of a peer.\n */\nexport class Awareness<T extends Value = Value> {\n inner: AwarenessWasm<T>;\n private peer: PeerID;\n private timer: number | undefined;\n private timeout: number;\n private listeners: Set<AwarenessListener> = new Set();\n constructor(peer: PeerID, timeout: number = 30000) {\n this.inner = new AwarenessWasm(peer, timeout);\n this.peer = peer;\n this.timeout = timeout;\n }\n\n apply(bytes: Uint8Array, origin = \"remote\") {\n const { updated, added } = this.inner.apply(bytes);\n this.listeners.forEach((listener) => {\n listener({ updated, added, removed: [] }, origin);\n });\n\n this.startTimerIfNotEmpty();\n }\n\n setLocalState(state: T) {\n const wasEmpty = this.inner.getState(this.peer) == null;\n this.inner.setLocalState(state);\n if (wasEmpty) {\n this.listeners.forEach((listener) => {\n listener(\n { updated: [], added: [this.inner.peer()], removed: [] },\n \"local\",\n );\n });\n } else {\n this.listeners.forEach((listener) => {\n listener(\n { updated: [this.inner.peer()], added: [], removed: [] },\n \"local\",\n );\n });\n }\n\n this.startTimerIfNotEmpty();\n }\n\n getLocalState(): T | undefined {\n return this.inner.getState(this.peer);\n }\n\n getAllStates(): Record<PeerID, T> {\n return this.inner.getAllStates();\n }\n\n encode(peers: PeerID[]): Uint8Array {\n return this.inner.encode(peers);\n }\n\n encodeAll(): Uint8Array {\n return this.inner.encodeAll();\n }\n\n addListener(listener: AwarenessListener) {\n this.listeners.add(listener);\n }\n\n removeListener(listener: AwarenessListener) {\n this.listeners.delete(listener);\n }\n\n peers(): PeerID[] {\n return this.inner.peers();\n }\n\n destroy() {\n clearInterval(this.timer);\n this.listeners.clear();\n }\n\n private startTimerIfNotEmpty() {\n if (this.inner.isEmpty() || this.timer != null) {\n return;\n }\n\n this.timer = setInterval(() => {\n const removed = this.inner.removeOutdated();\n if (removed.length > 0) {\n this.listeners.forEach((listener) => {\n listener({ updated: [], added: [], removed }, \"timeout\");\n });\n }\n if (this.inner.isEmpty()) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n }, this.timeout / 2) as unknown as number;\n }\n}\n","export {\n AwarenessWasm, Change, Container, ContainerID, ContainerType,\n Cursor, Delta, ExportMode, ImportBlobMetadata,\n JsonChange, JsonContainerID, JsonOp, JsonOpID, JsonSchema,\n JsonValue, ListOp, LoroCounter, LoroList, LoroMap, LoroDoc,\n LoroMovableList, LoroText, LoroTree, LoroTreeNode, MapOp, MovableListOp,\n OpId, PeerID, Side, TextOp, TreeID, TreeNodeValue, TreeOp, UndoConfig,\n UndoManager, UnknownOp, Value, VersionVector, decodeImportBlobMeta, setDebug,\n newContainerID, newRootContainerID\n} from \"loro-wasm\";\nimport {\n Container,\n ContainerID,\n Delta,\n LoroDoc,\n LoroList,\n LoroMap,\n LoroText,\n LoroTree,\n LoroCounter,\n OpId,\n TreeID,\n Value,\n} from \"loro-wasm\";\n\n/**\n * @deprecated Please use LoroDoc\n */\nexport class Loro extends LoroDoc { }\nexport { Awareness } from \"./awareness\";\n\nexport type Frontiers = OpId[];\n\n/**\n * Represents a path to identify the exact location of an event's target.\n * The path is composed of numbers (e.g., indices of a list container) strings\n * (e.g., keys of a map container) and TreeID (the node of a tree container),\n * indicating the absolute position of the event's source within a loro document.\n */\nexport type Path = (number | string | TreeID)[];\n\n/**\n * A batch of events that created by a single `import`/`transaction`/`checkout`.\n *\n * @prop by - How the event is triggered.\n * @prop origin - (Optional) Provides information about the origin of the event.\n * @prop diff - Contains the differential information related to the event.\n * @prop target - Identifies the container ID of the event's target.\n * @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.\n */\nexport interface LoroEventBatch {\n /**\n * How the event is triggered.\n *\n * - `local`: The event is triggered by a local transaction.\n * - `import`: The event is triggered by an import operation.\n * - `checkout`: The event is triggered by a checkout operation.\n */\n by: \"local\" | \"import\" | \"checkout\";\n origin?: string;\n /**\n * The container ID of the current event receiver.\n * It's undefined if the subscriber is on the root document.\n */\n currentTarget?: ContainerID;\n events: LoroEvent[];\n}\n\n/**\n * The concrete event of Loro.\n */\nexport interface LoroEvent {\n /**\n * The container ID of the event's target.\n */\n target: ContainerID;\n diff: Diff;\n /**\n * The absolute path of the event's emitter, which can be an index of a list container or a key of a map container.\n */\n path: Path;\n}\n\nexport type ListDiff = {\n type: \"list\";\n diff: Delta<(Value | Container)[]>[];\n};\n\nexport type TextDiff = {\n type: \"text\";\n diff: Delta<string>[];\n};\n\nexport type MapDiff = {\n type: \"map\";\n updated: Record<string, Value | Container | undefined>;\n};\n\nexport type TreeDiffItem =\n | {\n target: TreeID;\n action: \"create\";\n parent: TreeID | undefined;\n index: number;\n fractional_index: string;\n }\n | { target: TreeID; action: \"delete\"; old_parent: TreeID | undefined; old_index: number }\n | {\n target: TreeID;\n action: \"move\";\n parent: TreeID | undefined;\n index: number;\n fractional_index: string;\n old_parent: TreeID | undefined;\n old_index: number;\n };\n\nexport type TreeDiff = {\n type: \"tree\";\n diff: TreeDiffItem[];\n};\n\nexport type CounterDiff = {\n type: \"counter\";\n increment: number;\n}\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff | CounterDiff;\n\ninterface Listener {\n (event: LoroEventBatch): void;\n}\n\nconst CONTAINER_TYPES = [\"Map\", \"Text\", \"List\", \"Tree\", \"MovableList\", \"Counter\"];\n\nexport function isContainerId(s: string): s is ContainerID {\n return s.startsWith(\"cid:\");\n}\n\n/** Whether the value is a container.\n *\n * # Example\n *\n * ```ts\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * const list = doc.getList(\"list\");\n * const text = doc.getText(\"text\");\n * isContainer(map); // true\n * isContainer(list); // true\n * isContainer(text); // true\n * isContainer(123); // false\n * isContainer(\"123\"); // false\n * isContainer({}); // false\n */\nexport function isContainer(value: any): value is Container {\n if (typeof value !== \"object\" || value == null) {\n return false;\n }\n\n const p = Object.getPrototypeOf(value);\n if (p == null || typeof p !== \"object\" || typeof p[\"kind\"] !== \"function\") {\n return false;\n }\n\n return CONTAINER_TYPES.includes(value.kind());\n}\n\n/** Get the type of a value that may be a container.\n *\n * # Example\n *\n * ```ts\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * const list = doc.getList(\"list\");\n * const text = doc.getText(\"text\");\n * getType(map); // \"Map\"\n * getType(list); // \"List\"\n * getType(text); // \"Text\"\n * getType(123); // \"Json\"\n * getType(\"123\"); // \"Json\"\n * getType({}); // \"Json\"\n * ```\n */\nexport function getType<T>(\n value: T,\n): T extends LoroText\n ? \"Text\"\n : T extends LoroMap<any>\n ? \"Map\"\n : T extends LoroTree<any>\n ? \"Tree\"\n : T extends LoroList<any>\n ? \"List\"\n : T extends LoroCounter ? \"Counter\"\n : \"Json\" {\n if (isContainer(value)) {\n return value.kind() as unknown as any;\n }\n\n return \"Json\" as any;\n}\n\ndeclare module \"loro-wasm\" {\n interface LoroDoc {\n subscribe(listener: Listener): number;\n }\n\n interface UndoManager {\n /**\n * Set the callback function that is called when an undo/redo step is pushed.\n * The function can return a meta data value that will be attached to the given stack item.\n *\n * @param listener - The callback function.\n */\n setOnPush(listener?: UndoConfig[\"onPush\"]): void;\n /**\n * Set the callback function that is called when an undo/redo step is popped.\n * The function will have a meta data value that was attached to the given stack item when `onPush` was called.\n *\n * @param listener - The callback function.\n */\n setOnPop(listener?: UndoConfig[\"onPop\"]): void;\n }\n\n interface LoroDoc<\n T extends Record<string, Container> = Record<string, Container>,\n > {\n /**\n * Get a LoroMap by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * ```\n */\n getMap<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroMap ? T[Key] : LoroMap;\n /**\n * Get a LoroList by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * ```\n */\n getList<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroList ? T[Key] : LoroList;\n /**\n * Get a LoroMovableList by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * ```\n */\n getMovableList<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroMovableList ? T[Key] : LoroMovableList;\n /**\n * Get a LoroTree by container id\n *\n * The object returned is a new js object each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const tree = doc.getTree(\"tree\");\n * ```\n */\n getTree<Key extends keyof T | ContainerID>(\n name: Key,\n ): T[Key] extends LoroTree ? T[Key] : LoroTree;\n getText(key: string | ContainerID): LoroText;\n }\n\n interface LoroList<T = unknown> {\n new(): LoroList<T>;\n /**\n * Get elements of the list. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.insertContainer(3, new LoroText());\n * console.log(list.value); // [100, \"foo\", true, LoroText];\n * ```\n */\n toArray(): T[];\n /**\n * Insert a container at the index.\n *\n * @example\n * ```ts\n * import { LoroDoc, LoroText } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * const text = list.insertContainer(1, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [100, \"Hello\"];\n * ```\n */\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n /**\n * Get the value at the index. If the value is a container, the corresponding handler will be returned.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * console.log(list.get(0)); // 100\n * console.log(list.get(1)); // undefined\n * ```\n */\n get(index: number): T;\n /**\n * Insert a value at index.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * console.log(list.value); // [100, \"foo\", true];\n * ```\n */\n insert<V extends T>(pos: number, value: Exclude<V, Container>): void;\n delete(pos: number, len: number): void;\n push<V extends T>(value: Exclude<V, Container>): void;\n subscribe(listener: Listener): number;\n getAttached(): undefined | LoroList<T>;\n }\n\n interface LoroMovableList<T = unknown> {\n new(): LoroMovableList<T>;\n /**\n * Get elements of the list. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * @example\n * ```ts\n * import { LoroDoc, LoroText } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.insertContainer(3, new LoroText());\n * console.log(list.value); // [100, \"foo\", true, LoroText];\n * ```\n */\n toArray(): T[];\n /**\n * Insert a container at the index.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * const text = list.insertContainer(1, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [100, \"Hello\"];\n * ```\n */\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n /**\n * Get the value at the index. If the value is a container, the corresponding handler will be returned.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * console.log(list.get(0)); // 100\n * console.log(list.get(1)); // undefined\n * ```\n */\n get(index: number): T;\n /**\n * Insert a value at index.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * console.log(list.value); // [100, \"foo\", true];\n * ```\n */\n insert<V extends T>(pos: number, value: Exclude<V, Container>): void;\n delete(pos: number, len: number): void;\n push<V extends T>(value: Exclude<V, Container>): void;\n subscribe(listener: Listener): number;\n getAttached(): undefined | LoroMovableList<T>;\n /**\n * Set the value at the given position.\n *\n * It's different from `delete` + `insert` that it will replace the value at the position.\n *\n * For example, if you have a list `[1, 2, 3]`, and you call `set(1, 100)`, the list will be `[1, 100, 3]`.\n * If concurrently someone call `set(1, 200)`, the list will be `[1, 200, 3]` or `[1, 100, 3]`.\n *\n * But if you use `delete` + `insert` to simulate the set operation, they may create redundant operations\n * and the final result will be `[1, 100, 200, 3]` or `[1, 200, 100, 3]`.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getList(\"list\");\n * list.insert(0, 100);\n * list.insert(1, \"foo\");\n * list.insert(2, true);\n * list.set(1, \"bar\");\n * console.log(list.value); // [100, \"bar\", true];\n * ```\n */\n set<V extends T>(pos: number, value: Exclude<V, Container>): void;\n /**\n * Set a container at the index.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const list = doc.getMovableList(\"list\");\n * list.insert(0, 100);\n * const text = list.setContainer(0, new LoroText());\n * text.insert(0, \"Hello\");\n * console.log(list.toJSON()); // [\"Hello\"];\n * ```\n */\n setContainer<C extends Container>(\n pos: number,\n child: C,\n ): T extends C ? T : C;\n }\n\n interface LoroMap<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n new(): LoroMap<T>;\n /**\n * Get the value of the key. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * The object returned is a new js object each time because it need to cross\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const bar = map.get(\"foo\");\n * ```\n */\n getOrCreateContainer<C extends Container>(key: string, child: C): C;\n /**\n * Set the key with a container.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const text = map.setContainer(\"text\", new LoroText());\n * const list = map.setContainer(\"list\", new LoroText());\n * ```\n */\n setContainer<C extends Container, Key extends keyof T>(\n key: Key,\n child: C,\n ): NonNullableType<T[Key]> extends C ? NonNullableType<T[Key]> : C;\n /**\n * Get the value of the key. If the value is a child container, the corresponding\n * `Container` will be returned.\n *\n * The object/value returned is a new js object/value each time because it need to cross\n * the WASM boundary.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * const bar = map.get(\"foo\");\n * ```\n */\n get<Key extends keyof T>(key: Key): T[Key];\n /**\n * Set the key with the value.\n *\n * If the value of the key is exist, the old value will be updated.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const map = doc.getMap(\"map\");\n * map.set(\"foo\", \"bar\");\n * map.set(\"foo\", \"baz\");\n * ```\n */\n set<Key extends keyof T, V extends T[Key]>(\n key: Key,\n value: Exclude<V, Container>,\n ): void;\n delete(key: string): void;\n subscribe(listener: Listener): number;\n }\n\n interface LoroText {\n new(): LoroText;\n insert(pos: number, text: string): void;\n delete(pos: number, len: number): void;\n subscribe(listener: Listener): number;\n }\n\n interface LoroTree<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n new(): LoroTree<T>;\n /**\n * Create a new tree node as the child of parent and return a `LoroTreeNode` instance.\n * If the parent is undefined, the tree node will be a root node.\n *\n * If the index is not provided, the new node will be appended to the end.\n *\n * @example\n * ```ts\n * import { LoroDoc } from \"loro-crdt\";\n *\n * const doc = new LoroDoc();\n * const tree = doc.getTree(\"tree\");\n * const root = tree.createNode();\n * const node = tree.createNode(undefined, 0);\n *\n * // undefined\n * // / \\\n * // node root\n * ```\n */\n createNode(parent?: TreeID, index?: number): LoroTreeNode<T>;\n move(target: TreeID, parent?: TreeID, index?: number): void;\n delete(target: TreeID): void;\n has(target: TreeID): boolean;\n /**\n * Get LoroTreeNode by the TreeID.\n */\n getNodeByID(target: TreeID): LoroTreeNode<T>;\n subscribe(listener: Listener): number;\n }\n\n interface LoroTreeNode<\n T extends Record<string, unknown> = Record<string, unknown>,\n > {\n /**\n * Get the associated metadata map container of a tree node.\n */\n readonly data: LoroMap<T>;\n /** \n * Create a new node as the child of the current node and\n * return an instance of `LoroTreeNode`.\n *\n * If the index is not provided, the new node will be appended to the end.\n *\n * @example\n * ```typescript\n * import { LoroDoc } from \"loro-crdt\";\n *\n * let doc = new LoroDoc();\n * let tree = doc.getTree(\"tree\");\n * let root = tree.createNode();\n * let node = root.createNode();\n * let node2 = root.createNode(0);\n * // root\n * // / \\\n * // node2 node\n * ```\n */\n createNode(index?: number): LoroTreeNode<T>;\n move(parent?: LoroTreeNode<T>, index?: number): void;\n parent(): LoroTreeNode<T> | undefined;\n /**\n * Get the children of this node.\n *\n * The objects returned are new js objects each time because they need to cross\n * the WASM boundary.\n */\n children(): Array<LoroTreeNode<T>> | undefined;\n }\n\n interface AwarenessWasm<T extends Value = Value> {\n getState(peer: PeerID): T | undefined;\n getTimestamp(peer: PeerID): number | undefined;\n getAllStates(): Record<PeerID, T>;\n setLocalState(value: T): void;\n removeOutdated(): PeerID[];\n }\n}\n\ntype NonNullableType<T> = Exclude<T, null | undefined>;\n"],"names":["LoroDoc"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loro-crdt",
3
- "version": "0.16.12",
3
+ "version": "1.0.0-alpha.1",
4
4
  "description": "Loro CRDTs is a high-performance CRDT framework that makes your app state synchronized, collaborative and maintainable effortlessly.",
5
5
  "keywords": [
6
6
  "crdt",
@@ -21,7 +21,7 @@
21
21
  "homepage": "https://loro.dev",
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "loro-wasm": "0.16.12"
24
+ "loro-wasm": "1.0.0-alpha.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@rollup/plugin-node-resolve": "^15.0.1",