loro-crdt 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.13.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix type errors and conversion from js->rust error
8
+ - Updated dependencies
9
+ - loro-wasm@0.13.1
10
+
11
+ ## 0.13.0
12
+
13
+ ### Minor Changes
14
+
15
+ - BREAKING CHANGE: `detached` mode for Containers #300
16
+
17
+ Now creating sub-containers is much easier.
18
+
19
+ A container can be either attached to a document or detached. When it's detached, its history/state is not persisted. You can attach a container to a document by inserting it into an existing attached container. Once a container is attached, its state, along with all of its descendants's states, will be recreated in the document. After attaching, the container and its descendants will each have their corresponding "attached" version of themselves.
20
+
21
+ When a detached container x is attached to a document, you can use `x.getAttached()` to obtain the corresponding attached container.
22
+
23
+ When we use const text = new LoroList(), it's not attached to a doc. But we can insert it into a doc by map.insertContainer(”t”, text), where the map is attached. But if we want the operations on the text to be recorded to the doc, we now need to get its attached version. So we can use “let attachedText = text.getAttached()”
24
+
25
+ ### Patch Changes
26
+
27
+ - Updated dependencies
28
+ - loro-wasm@0.13.0
29
+
3
30
  ## 0.12.0
4
31
 
5
32
  ### Minor Changes
package/dist/loro.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Value, Container, TreeID, OpId, ContainerID, Delta, LoroText, LoroMap, LoroTree, LoroList } from 'loro-wasm';
1
+ import { ContainerID, Container, Value, TreeID, OpId, Delta, LoroText, LoroMap, LoroTree, LoroList } from 'loro-wasm';
2
2
  export * from 'loro-wasm';
3
3
  export { Loro } from 'loro-wasm';
4
4
 
@@ -115,7 +115,7 @@ declare function isContainer(value: any): value is Container;
115
115
  * getType({}); // "Json"
116
116
  * ```
117
117
  */
118
- declare function getType<T>(value: T): T extends LoroText ? "Text" : T extends LoroMap ? "Map" : T extends LoroTree ? "Tree" : T extends LoroList ? "List" : "Json";
118
+ 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" : "Json";
119
119
  declare module "loro-wasm" {
120
120
  interface Loro {
121
121
  subscribe(listener: Listener): number;
@@ -123,31 +123,26 @@ declare module "loro-wasm" {
123
123
  interface Loro<T extends Record<string, any> = Record<string, any>> {
124
124
  getTypedMap<Key extends keyof T & string>(name: Key): T[Key] extends LoroMap ? T[Key] : never;
125
125
  getTypedList<Key extends keyof T & string>(name: Key): T[Key] extends LoroList ? T[Key] : never;
126
+ getMap(key: string | ContainerID): LoroMap<T[string]>;
127
+ getList(key: string | ContainerID): LoroList<T[string]>;
128
+ getTree(key: string | ContainerID): LoroTree<T[string]>;
129
+ getText(key: string | ContainerID): LoroText;
126
130
  }
127
131
  interface LoroList<T extends any[] = any[]> {
128
- insertContainer(pos: number, container: "Map"): LoroMap;
129
- insertContainer(pos: number, container: "List"): LoroList;
130
- insertContainer(pos: number, container: "Text"): LoroText;
131
- insertContainer(pos: number, container: "Tree"): LoroTree;
132
- insertContainer(pos: number, container: string): never;
132
+ new (): LoroList<T>;
133
+ insertContainer<C extends Container>(pos: number, child: C): C;
133
134
  get(index: number): undefined | Value | Container;
134
135
  getTyped<Key extends keyof T & number>(loro: Loro, index: Key): T[Key];
135
136
  insertTyped<Key extends keyof T & number>(pos: Key, value: T[Key]): void;
136
137
  insert(pos: number, value: Value): void;
137
138
  delete(pos: number, len: number): void;
138
139
  subscribe(txn: Loro, listener: Listener): number;
140
+ getAttached(): undefined | LoroList<T>;
139
141
  }
140
142
  interface LoroMap<T extends Record<string, any> = Record<string, any>> {
141
- getOrCreateContainer(key: string, container_type: "Map"): LoroMap;
142
- getOrCreateContainer(key: string, container_type: "List"): LoroList;
143
- getOrCreateContainer(key: string, container_type: "Text"): LoroText;
144
- getOrCreateContainer(key: string, container_type: "Tree"): LoroTree;
145
- getOrCreateContainer(key: string, container_type: string): never;
146
- setContainer(key: string, container_type: "Map"): LoroMap;
147
- setContainer(key: string, container_type: "List"): LoroList;
148
- setContainer(key: string, container_type: "Text"): LoroText;
149
- setContainer(key: string, container_type: "Tree"): LoroTree;
150
- setContainer(key: string, container_type: string): never;
143
+ new (): LoroMap<T>;
144
+ getOrCreateContainer<C extends Container>(key: string, child: C): C;
145
+ setContainer<C extends Container>(key: string, child: C): C;
151
146
  get(key: string): undefined | Value | Container;
152
147
  getTyped<Key extends keyof T & string>(txn: Loro, key: Key): T[Key];
153
148
  set(key: string, value: Value): void;
@@ -156,25 +151,27 @@ declare module "loro-wasm" {
156
151
  subscribe(txn: Loro, listener: Listener): number;
157
152
  }
158
153
  interface LoroText {
154
+ new (): LoroText;
159
155
  insert(pos: number, text: string): void;
160
156
  delete(pos: number, len: number): void;
161
157
  subscribe(txn: Loro, listener: Listener): number;
162
158
  }
163
- interface LoroTree {
164
- createNode(parent: TreeID | undefined): LoroTreeNode;
159
+ interface LoroTree<T extends Record<string, any> = Record<string, any>> {
160
+ new (): LoroTree<T>;
161
+ createNode(parent: TreeID | undefined): LoroTreeNode<T>;
165
162
  move(target: TreeID, parent: TreeID | undefined): void;
166
163
  delete(target: TreeID): void;
167
164
  has(target: TreeID): boolean;
168
165
  getNodeByID(target: TreeID): LoroTreeNode;
169
166
  subscribe(txn: Loro, listener: Listener): number;
170
167
  }
171
- interface LoroTreeNode {
172
- readonly data: LoroMap;
173
- createNode(): LoroTreeNode;
168
+ interface LoroTreeNode<T extends Record<string, any> = Record<string, any>> {
169
+ readonly data: LoroMap<T>;
170
+ createNode(): LoroTreeNode<T>;
174
171
  setAsRoot(): void;
175
- moveTo(parent: LoroTreeNode): void;
172
+ moveTo(parent: LoroTreeNode<T>): void;
176
173
  parent(): LoroTreeNode | undefined;
177
- children(): Array<LoroTreeNode>;
174
+ children(): Array<LoroTreeNode<T>>;
178
175
  }
179
176
  }
180
177
 
package/dist/loro.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"loro.js","sources":["../src/index.ts"],"sourcesContent":["export * from \"loro-wasm\";\nimport {\n Container,\n Delta,\n LoroText,\n LoroTree,\n LoroTreeNode,\n OpId,\n Value,\n ContainerID,\n Loro,\n LoroList,\n LoroMap,\n TreeID,\n} from \"loro-wasm\";\n\nLoro.prototype.getTypedMap = function (...args) {\n return this.getMap(...args);\n};\nLoro.prototype.getTypedList = function (...args) {\n return this.getList(...args);\n};\nLoroList.prototype.getTyped = function (loro, index) {\n const value = this.get(index);\n if (typeof value === \"string\" && isContainerId(value)) {\n return loro.getContainerById(value);\n } else {\n return value;\n }\n};\nLoroList.prototype.insertTyped = function (...args) {\n return this.insert(...args);\n};\nLoroMap.prototype.getTyped = function (loro, key) {\n const value = this.get(key);\n if (typeof value === \"string\" && isContainerId(value)) {\n return loro.getContainerById(value);\n } else {\n return value;\n }\n};\nLoroMap.prototype.setTyped = function (...args) {\n return this.set(...args);\n};\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 local - Indicates whether the event is local.\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 local: boolean;\n /**\n * If true, this event was triggered by a checkout.\n */\n fromCheckout: boolean;\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 | { target: TreeID; action: \"create\"; parent: TreeID | undefined }\n | { target: TreeID; action: \"delete\" }\n | { target: TreeID; action: \"move\"; parent: TreeID | undefined };\n\nexport type TreeDiff = {\n type: \"tree\";\n diff: TreeDiffItem[];\n};\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;\n\ninterface Listener {\n (event: LoroEventBatch): void;\n}\n\nconst CONTAINER_TYPES = [\"Map\", \"Text\", \"List\", \"Tree\"];\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\n ? \"Map\"\n : T extends LoroTree\n ? \"Tree\"\n : T extends LoroList\n ? \"List\"\n : \"Json\" {\n if (isContainer(value)) {\n return value.kind();\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 Loro<T extends Record<string, any> = Record<string, any>> {\n getTypedMap<Key extends keyof T & string>(\n name: Key,\n ): T[Key] extends LoroMap ? T[Key] : never;\n getTypedList<Key extends keyof T & string>(\n name: Key,\n ): T[Key] extends LoroList ? T[Key] : never;\n }\n\n interface LoroList<T extends any[] = any[]> {\n insertContainer(pos: number, container: \"Map\"): LoroMap;\n insertContainer(pos: number, container: \"List\"): LoroList;\n insertContainer(pos: number, container: \"Text\"): LoroText;\n insertContainer(pos: number, container: \"Tree\"): LoroTree;\n insertContainer(pos: number, container: string): never;\n\n get(index: number): undefined | Value | Container;\n getTyped<Key extends keyof T & number>(loro: Loro, index: Key): T[Key];\n insertTyped<Key extends keyof T & number>(pos: Key, value: T[Key]): void;\n insert(pos: number, value: Value): void;\n delete(pos: number, len: number): void;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroMap<T extends Record<string, any> = Record<string, any>> {\n getOrCreateContainer(key: string, container_type: \"Map\"): LoroMap;\n getOrCreateContainer(key: string, container_type: \"List\"): LoroList;\n getOrCreateContainer(key: string, container_type: \"Text\"): LoroText;\n getOrCreateContainer(key: string, container_type: \"Tree\"): LoroTree;\n getOrCreateContainer(key: string, container_type: string): never;\n\n setContainer(key: string, container_type: \"Map\"): LoroMap;\n setContainer(key: string, container_type: \"List\"): LoroList;\n setContainer(key: string, container_type: \"Text\"): LoroText;\n setContainer(key: string, container_type: \"Tree\"): LoroTree;\n setContainer(key: string, container_type: string): never;\n\n get(key: string): undefined | Value | Container;\n getTyped<Key extends keyof T & string>(txn: Loro, key: Key): T[Key];\n set(key: string, value: Value): void;\n setTyped<Key extends keyof T & string>(key: Key, value: T[Key]): void;\n delete(key: string): void;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroText {\n insert(pos: number, text: string): void;\n delete(pos: number, len: number): void;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroTree {\n createNode(parent: TreeID | undefined): LoroTreeNode;\n move(target: TreeID, parent: TreeID | undefined): void;\n delete(target: TreeID): void;\n has(target: TreeID): boolean;\n getNodeByID(target: TreeID): LoroTreeNode;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroTreeNode {\n readonly data: LoroMap;\n createNode(): LoroTreeNode;\n setAsRoot(): void;\n moveTo(parent: LoroTreeNode): void;\n parent(): LoroTreeNode | undefined;\n children(): Array<LoroTreeNode>;\n }\n}\n"],"names":["Loro","LoroList","LoroMap"],"mappings":";;;;AAgBAA,aAAK,CAAA,SAAA,CAAU,WAAc,GAAA,SAAA,GAAa,IAAM,EAAA;AAC9C,EAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAG,IAAI,CAAA,CAAA;AAC5B,CAAA,CAAA;AACAA,aAAK,CAAA,SAAA,CAAU,YAAe,GAAA,SAAA,GAAa,IAAM,EAAA;AAC/C,EAAO,OAAA,IAAA,CAAK,OAAQ,CAAA,GAAG,IAAI,CAAA,CAAA;AAC7B,CAAA,CAAA;AACAC,iBAAA,CAAS,SAAU,CAAA,QAAA,GAAW,SAAU,IAAA,EAAM,KAAO,EAAA;AACnD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,KAAK,CAAA,CAAA;AAC5B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,aAAA,CAAc,KAAK,CAAG,EAAA;AACrD,IAAO,OAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,GAC7B,MAAA;AACL,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AACAA,iBAAS,CAAA,SAAA,CAAU,WAAc,GAAA,SAAA,GAAa,IAAM,EAAA;AAClD,EAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAG,IAAI,CAAA,CAAA;AAC5B,CAAA,CAAA;AACAC,gBAAA,CAAQ,SAAU,CAAA,QAAA,GAAW,SAAU,IAAA,EAAM,GAAK,EAAA;AAChD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAC1B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,aAAA,CAAc,KAAK,CAAG,EAAA;AACrD,IAAO,OAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,GAC7B,MAAA;AACL,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AACAA,gBAAQ,CAAA,SAAA,CAAU,QAAW,GAAA,SAAA,GAAa,IAAM,EAAA;AAC9C,EAAO,OAAA,IAAA,CAAK,GAAI,CAAA,GAAG,IAAI,CAAA,CAAA;AACzB,CAAA,CAAA;AAkFA,MAAM,eAAkB,GAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,QAAQ,MAAM,CAAA,CAAA;AAE/C,SAAS,cAAc,CAA6B,EAAA;AACzD,EAAO,OAAA,CAAA,CAAE,WAAW,MAAM,CAAA,CAAA;AAC5B,CAAA;AAoBO,SAAS,YAAY,KAAgC,EAAA;AAC1D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,KAAA,IAAS,IAAM,EAAA;AAC9C,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAM,MAAA,CAAA,GAAI,MAAO,CAAA,cAAA,CAAe,KAAK,CAAA,CAAA;AACrC,EAAI,IAAA,CAAA,IAAK,QAAQ,OAAO,CAAA,KAAM,YAAY,OAAO,CAAA,CAAE,MAAM,CAAA,KAAM,UAAY,EAAA;AACzE,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,OAAO,eAAgB,CAAA,QAAA,CAAS,KAAM,CAAA,IAAA,EAAM,CAAA,CAAA;AAC9C,CAAA;AAmBO,SAAS,QACd,KASS,EAAA;AACT,EAAI,IAAA,WAAA,CAAY,KAAK,CAAG,EAAA;AACtB,IAAA,OAAO,MAAM,IAAK,EAAA,CAAA;AAAA,GACpB;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"loro.js","sources":["../src/index.ts"],"sourcesContent":["export * from \"loro-wasm\";\nimport {\n Container,\n ContainerID,\n Delta,\n Loro,\n LoroList,\n LoroMap,\n LoroText,\n LoroTree,\n LoroTreeNode,\n OpId,\n TreeID,\n Value,\n} from \"loro-wasm\";\n\nLoro.prototype.getTypedMap = function (...args) {\n return this.getMap(...args);\n};\nLoro.prototype.getTypedList = function (...args) {\n return this.getList(...args);\n};\nLoroList.prototype.getTyped = function (loro, index) {\n const value = this.get(index);\n if (typeof value === \"string\" && isContainerId(value)) {\n return loro.getContainerById(value);\n } else {\n return value;\n }\n};\nLoroList.prototype.insertTyped = function (...args) {\n return this.insert(...args);\n};\nLoroMap.prototype.getTyped = function (loro, key) {\n const value = this.get(key);\n if (typeof value === \"string\" && isContainerId(value)) {\n return loro.getContainerById(value);\n } else {\n return value;\n }\n};\nLoroMap.prototype.setTyped = function (...args) {\n return this.set(...args);\n};\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 local - Indicates whether the event is local.\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 local: boolean;\n /**\n * If true, this event was triggered by a checkout.\n */\n fromCheckout: boolean;\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 | { target: TreeID; action: \"create\"; parent: TreeID | undefined }\n | { target: TreeID; action: \"delete\" }\n | { target: TreeID; action: \"move\"; parent: TreeID | undefined };\n\nexport type TreeDiff = {\n type: \"tree\";\n diff: TreeDiffItem[];\n};\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;\n\ninterface Listener {\n (event: LoroEventBatch): void;\n}\n\nconst CONTAINER_TYPES = [\"Map\", \"Text\", \"List\", \"Tree\"];\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 ? \"Text\"\n : T extends LoroMap<any> ? \"Map\"\n : T extends LoroTree<any> ? \"Tree\"\n : T extends LoroList<any> ? \"List\"\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 Loro<T extends Record<string, any> = Record<string, any>> {\n getTypedMap<Key extends keyof T & string>(\n name: Key,\n ): T[Key] extends LoroMap ? T[Key] : never;\n getTypedList<Key extends keyof T & string>(\n name: Key,\n ): T[Key] extends LoroList ? T[Key] : never;\n getMap(key: string | ContainerID): LoroMap<T[string]>;\n getList(key: string | ContainerID): LoroList<T[string]>;\n getTree(key: string | ContainerID): LoroTree<T[string]>;\n getText(key: string | ContainerID): LoroText;\n }\n\n interface LoroList<\n T extends any[] = any[],\n > {\n new (): LoroList<T>;\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): C;\n get(index: number): undefined | Value | Container;\n getTyped<Key extends keyof T & number>(loro: Loro, index: Key): T[Key];\n insertTyped<Key extends keyof T & number>(pos: Key, value: T[Key]): void;\n insert(pos: number, value: Value): void;\n delete(pos: number, len: number): void;\n subscribe(txn: Loro, listener: Listener): number;\n getAttached(): undefined | LoroList<T>;\n }\n\n interface LoroMap<\n T extends Record<string, any> = Record<string, any>,\n > {\n new (): LoroMap<T>;\n getOrCreateContainer<C extends Container>(\n key: string,\n child: C,\n ): C;\n setContainer<C extends Container>(\n key: string,\n child: C,\n ): C;\n get(key: string): undefined | Value | Container;\n getTyped<Key extends keyof T & string>(txn: Loro, key: Key): T[Key];\n set(key: string, value: Value): void;\n setTyped<Key extends keyof T & string>(key: Key, value: T[Key]): void;\n delete(key: string): void;\n subscribe(txn: Loro, 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(txn: Loro, listener: Listener): number;\n }\n\n interface LoroTree<\n T extends Record<string, any> = Record<string, any>,\n > {\n new (): LoroTree<T>;\n createNode(parent: TreeID | undefined): LoroTreeNode<T>;\n move(target: TreeID, parent: TreeID | undefined): void;\n delete(target: TreeID): void;\n has(target: TreeID): boolean;\n getNodeByID(target: TreeID): LoroTreeNode;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroTreeNode<\n T extends Record<string, any> = Record<string, any>,\n > {\n readonly data: LoroMap<T>;\n createNode(): LoroTreeNode<T>;\n setAsRoot(): void;\n moveTo(parent: LoroTreeNode<T>): void;\n parent(): LoroTreeNode | undefined;\n children(): Array<LoroTreeNode<T>>;\n }\n}\n"],"names":["Loro","LoroList","LoroMap"],"mappings":";;;;AAgBAA,aAAK,CAAA,SAAA,CAAU,WAAc,GAAA,SAAA,GAAa,IAAM,EAAA;AAC9C,EAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAG,IAAI,CAAA,CAAA;AAC5B,CAAA,CAAA;AACAA,aAAK,CAAA,SAAA,CAAU,YAAe,GAAA,SAAA,GAAa,IAAM,EAAA;AAC/C,EAAO,OAAA,IAAA,CAAK,OAAQ,CAAA,GAAG,IAAI,CAAA,CAAA;AAC7B,CAAA,CAAA;AACAC,iBAAA,CAAS,SAAU,CAAA,QAAA,GAAW,SAAU,IAAA,EAAM,KAAO,EAAA;AACnD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,KAAK,CAAA,CAAA;AAC5B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,aAAA,CAAc,KAAK,CAAG,EAAA;AACrD,IAAO,OAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,GAC7B,MAAA;AACL,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AACAA,iBAAS,CAAA,SAAA,CAAU,WAAc,GAAA,SAAA,GAAa,IAAM,EAAA;AAClD,EAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAG,IAAI,CAAA,CAAA;AAC5B,CAAA,CAAA;AACAC,gBAAA,CAAQ,SAAU,CAAA,QAAA,GAAW,SAAU,IAAA,EAAM,GAAK,EAAA;AAChD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAC1B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,aAAA,CAAc,KAAK,CAAG,EAAA;AACrD,IAAO,OAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,GAC7B,MAAA;AACL,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AACAA,gBAAQ,CAAA,SAAA,CAAU,QAAW,GAAA,SAAA,GAAa,IAAM,EAAA;AAC9C,EAAO,OAAA,IAAA,CAAK,GAAI,CAAA,GAAG,IAAI,CAAA,CAAA;AACzB,CAAA,CAAA;AAkFA,MAAM,eAAkB,GAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,QAAQ,MAAM,CAAA,CAAA;AAE/C,SAAS,cAAc,CAA6B,EAAA;AACzD,EAAO,OAAA,CAAA,CAAE,WAAW,MAAM,CAAA,CAAA;AAC5B,CAAA;AAoBO,SAAS,YAAY,KAAgC,EAAA;AAC1D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,KAAA,IAAS,IAAM,EAAA;AAC9C,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAM,MAAA,CAAA,GAAI,MAAO,CAAA,cAAA,CAAe,KAAK,CAAA,CAAA;AACrC,EAAI,IAAA,CAAA,IAAK,QAAQ,OAAO,CAAA,KAAM,YAAY,OAAO,CAAA,CAAE,MAAM,CAAA,KAAM,UAAY,EAAA;AACzE,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,OAAO,eAAgB,CAAA,QAAA,CAAS,KAAM,CAAA,IAAA,EAAM,CAAA,CAAA;AAC9C,CAAA;AAmBO,SAAS,QACd,KAKS,EAAA;AACT,EAAI,IAAA,WAAA,CAAY,KAAK,CAAG,EAAA;AACtB,IAAA,OAAO,MAAM,IAAK,EAAA,CAAA;AAAA,GACpB;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;;;;;;;;;;;;;"}
package/dist/loro.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"loro.mjs","sources":["../src/index.ts"],"sourcesContent":["export * from \"loro-wasm\";\nimport {\n Container,\n Delta,\n LoroText,\n LoroTree,\n LoroTreeNode,\n OpId,\n Value,\n ContainerID,\n Loro,\n LoroList,\n LoroMap,\n TreeID,\n} from \"loro-wasm\";\n\nLoro.prototype.getTypedMap = function (...args) {\n return this.getMap(...args);\n};\nLoro.prototype.getTypedList = function (...args) {\n return this.getList(...args);\n};\nLoroList.prototype.getTyped = function (loro, index) {\n const value = this.get(index);\n if (typeof value === \"string\" && isContainerId(value)) {\n return loro.getContainerById(value);\n } else {\n return value;\n }\n};\nLoroList.prototype.insertTyped = function (...args) {\n return this.insert(...args);\n};\nLoroMap.prototype.getTyped = function (loro, key) {\n const value = this.get(key);\n if (typeof value === \"string\" && isContainerId(value)) {\n return loro.getContainerById(value);\n } else {\n return value;\n }\n};\nLoroMap.prototype.setTyped = function (...args) {\n return this.set(...args);\n};\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 local - Indicates whether the event is local.\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 local: boolean;\n /**\n * If true, this event was triggered by a checkout.\n */\n fromCheckout: boolean;\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 | { target: TreeID; action: \"create\"; parent: TreeID | undefined }\n | { target: TreeID; action: \"delete\" }\n | { target: TreeID; action: \"move\"; parent: TreeID | undefined };\n\nexport type TreeDiff = {\n type: \"tree\";\n diff: TreeDiffItem[];\n};\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;\n\ninterface Listener {\n (event: LoroEventBatch): void;\n}\n\nconst CONTAINER_TYPES = [\"Map\", \"Text\", \"List\", \"Tree\"];\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\n ? \"Map\"\n : T extends LoroTree\n ? \"Tree\"\n : T extends LoroList\n ? \"List\"\n : \"Json\" {\n if (isContainer(value)) {\n return value.kind();\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 Loro<T extends Record<string, any> = Record<string, any>> {\n getTypedMap<Key extends keyof T & string>(\n name: Key,\n ): T[Key] extends LoroMap ? T[Key] : never;\n getTypedList<Key extends keyof T & string>(\n name: Key,\n ): T[Key] extends LoroList ? T[Key] : never;\n }\n\n interface LoroList<T extends any[] = any[]> {\n insertContainer(pos: number, container: \"Map\"): LoroMap;\n insertContainer(pos: number, container: \"List\"): LoroList;\n insertContainer(pos: number, container: \"Text\"): LoroText;\n insertContainer(pos: number, container: \"Tree\"): LoroTree;\n insertContainer(pos: number, container: string): never;\n\n get(index: number): undefined | Value | Container;\n getTyped<Key extends keyof T & number>(loro: Loro, index: Key): T[Key];\n insertTyped<Key extends keyof T & number>(pos: Key, value: T[Key]): void;\n insert(pos: number, value: Value): void;\n delete(pos: number, len: number): void;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroMap<T extends Record<string, any> = Record<string, any>> {\n getOrCreateContainer(key: string, container_type: \"Map\"): LoroMap;\n getOrCreateContainer(key: string, container_type: \"List\"): LoroList;\n getOrCreateContainer(key: string, container_type: \"Text\"): LoroText;\n getOrCreateContainer(key: string, container_type: \"Tree\"): LoroTree;\n getOrCreateContainer(key: string, container_type: string): never;\n\n setContainer(key: string, container_type: \"Map\"): LoroMap;\n setContainer(key: string, container_type: \"List\"): LoroList;\n setContainer(key: string, container_type: \"Text\"): LoroText;\n setContainer(key: string, container_type: \"Tree\"): LoroTree;\n setContainer(key: string, container_type: string): never;\n\n get(key: string): undefined | Value | Container;\n getTyped<Key extends keyof T & string>(txn: Loro, key: Key): T[Key];\n set(key: string, value: Value): void;\n setTyped<Key extends keyof T & string>(key: Key, value: T[Key]): void;\n delete(key: string): void;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroText {\n insert(pos: number, text: string): void;\n delete(pos: number, len: number): void;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroTree {\n createNode(parent: TreeID | undefined): LoroTreeNode;\n move(target: TreeID, parent: TreeID | undefined): void;\n delete(target: TreeID): void;\n has(target: TreeID): boolean;\n getNodeByID(target: TreeID): LoroTreeNode;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroTreeNode {\n readonly data: LoroMap;\n createNode(): LoroTreeNode;\n setAsRoot(): void;\n moveTo(parent: LoroTreeNode): void;\n parent(): LoroTreeNode | undefined;\n children(): Array<LoroTreeNode>;\n }\n}\n"],"names":[],"mappings":";;;;AAgBA,IAAK,CAAA,SAAA,CAAU,WAAc,GAAA,SAAA,GAAa,IAAM,EAAA;AAC9C,EAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAG,IAAI,CAAA,CAAA;AAC5B,CAAA,CAAA;AACA,IAAK,CAAA,SAAA,CAAU,YAAe,GAAA,SAAA,GAAa,IAAM,EAAA;AAC/C,EAAO,OAAA,IAAA,CAAK,OAAQ,CAAA,GAAG,IAAI,CAAA,CAAA;AAC7B,CAAA,CAAA;AACA,QAAA,CAAS,SAAU,CAAA,QAAA,GAAW,SAAU,IAAA,EAAM,KAAO,EAAA;AACnD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,KAAK,CAAA,CAAA;AAC5B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,aAAA,CAAc,KAAK,CAAG,EAAA;AACrD,IAAO,OAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,GAC7B,MAAA;AACL,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AACA,QAAS,CAAA,SAAA,CAAU,WAAc,GAAA,SAAA,GAAa,IAAM,EAAA;AAClD,EAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAG,IAAI,CAAA,CAAA;AAC5B,CAAA,CAAA;AACA,OAAA,CAAQ,SAAU,CAAA,QAAA,GAAW,SAAU,IAAA,EAAM,GAAK,EAAA;AAChD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAC1B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,aAAA,CAAc,KAAK,CAAG,EAAA;AACrD,IAAO,OAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,GAC7B,MAAA;AACL,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AACA,OAAQ,CAAA,SAAA,CAAU,QAAW,GAAA,SAAA,GAAa,IAAM,EAAA;AAC9C,EAAO,OAAA,IAAA,CAAK,GAAI,CAAA,GAAG,IAAI,CAAA,CAAA;AACzB,CAAA,CAAA;AAkFA,MAAM,eAAkB,GAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,QAAQ,MAAM,CAAA,CAAA;AAE/C,SAAS,cAAc,CAA6B,EAAA;AACzD,EAAO,OAAA,CAAA,CAAE,WAAW,MAAM,CAAA,CAAA;AAC5B,CAAA;AAoBO,SAAS,YAAY,KAAgC,EAAA;AAC1D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,KAAA,IAAS,IAAM,EAAA;AAC9C,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAM,MAAA,CAAA,GAAI,MAAO,CAAA,cAAA,CAAe,KAAK,CAAA,CAAA;AACrC,EAAI,IAAA,CAAA,IAAK,QAAQ,OAAO,CAAA,KAAM,YAAY,OAAO,CAAA,CAAE,MAAM,CAAA,KAAM,UAAY,EAAA;AACzE,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,OAAO,eAAgB,CAAA,QAAA,CAAS,KAAM,CAAA,IAAA,EAAM,CAAA,CAAA;AAC9C,CAAA;AAmBO,SAAS,QACd,KASS,EAAA;AACT,EAAI,IAAA,WAAA,CAAY,KAAK,CAAG,EAAA;AACtB,IAAA,OAAO,MAAM,IAAK,EAAA,CAAA;AAAA,GACpB;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
1
+ {"version":3,"file":"loro.mjs","sources":["../src/index.ts"],"sourcesContent":["export * from \"loro-wasm\";\nimport {\n Container,\n ContainerID,\n Delta,\n Loro,\n LoroList,\n LoroMap,\n LoroText,\n LoroTree,\n LoroTreeNode,\n OpId,\n TreeID,\n Value,\n} from \"loro-wasm\";\n\nLoro.prototype.getTypedMap = function (...args) {\n return this.getMap(...args);\n};\nLoro.prototype.getTypedList = function (...args) {\n return this.getList(...args);\n};\nLoroList.prototype.getTyped = function (loro, index) {\n const value = this.get(index);\n if (typeof value === \"string\" && isContainerId(value)) {\n return loro.getContainerById(value);\n } else {\n return value;\n }\n};\nLoroList.prototype.insertTyped = function (...args) {\n return this.insert(...args);\n};\nLoroMap.prototype.getTyped = function (loro, key) {\n const value = this.get(key);\n if (typeof value === \"string\" && isContainerId(value)) {\n return loro.getContainerById(value);\n } else {\n return value;\n }\n};\nLoroMap.prototype.setTyped = function (...args) {\n return this.set(...args);\n};\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 local - Indicates whether the event is local.\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 local: boolean;\n /**\n * If true, this event was triggered by a checkout.\n */\n fromCheckout: boolean;\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 | { target: TreeID; action: \"create\"; parent: TreeID | undefined }\n | { target: TreeID; action: \"delete\" }\n | { target: TreeID; action: \"move\"; parent: TreeID | undefined };\n\nexport type TreeDiff = {\n type: \"tree\";\n diff: TreeDiffItem[];\n};\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;\n\ninterface Listener {\n (event: LoroEventBatch): void;\n}\n\nconst CONTAINER_TYPES = [\"Map\", \"Text\", \"List\", \"Tree\"];\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 ? \"Text\"\n : T extends LoroMap<any> ? \"Map\"\n : T extends LoroTree<any> ? \"Tree\"\n : T extends LoroList<any> ? \"List\"\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 Loro<T extends Record<string, any> = Record<string, any>> {\n getTypedMap<Key extends keyof T & string>(\n name: Key,\n ): T[Key] extends LoroMap ? T[Key] : never;\n getTypedList<Key extends keyof T & string>(\n name: Key,\n ): T[Key] extends LoroList ? T[Key] : never;\n getMap(key: string | ContainerID): LoroMap<T[string]>;\n getList(key: string | ContainerID): LoroList<T[string]>;\n getTree(key: string | ContainerID): LoroTree<T[string]>;\n getText(key: string | ContainerID): LoroText;\n }\n\n interface LoroList<\n T extends any[] = any[],\n > {\n new (): LoroList<T>;\n insertContainer<C extends Container>(\n pos: number,\n child: C,\n ): C;\n get(index: number): undefined | Value | Container;\n getTyped<Key extends keyof T & number>(loro: Loro, index: Key): T[Key];\n insertTyped<Key extends keyof T & number>(pos: Key, value: T[Key]): void;\n insert(pos: number, value: Value): void;\n delete(pos: number, len: number): void;\n subscribe(txn: Loro, listener: Listener): number;\n getAttached(): undefined | LoroList<T>;\n }\n\n interface LoroMap<\n T extends Record<string, any> = Record<string, any>,\n > {\n new (): LoroMap<T>;\n getOrCreateContainer<C extends Container>(\n key: string,\n child: C,\n ): C;\n setContainer<C extends Container>(\n key: string,\n child: C,\n ): C;\n get(key: string): undefined | Value | Container;\n getTyped<Key extends keyof T & string>(txn: Loro, key: Key): T[Key];\n set(key: string, value: Value): void;\n setTyped<Key extends keyof T & string>(key: Key, value: T[Key]): void;\n delete(key: string): void;\n subscribe(txn: Loro, 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(txn: Loro, listener: Listener): number;\n }\n\n interface LoroTree<\n T extends Record<string, any> = Record<string, any>,\n > {\n new (): LoroTree<T>;\n createNode(parent: TreeID | undefined): LoroTreeNode<T>;\n move(target: TreeID, parent: TreeID | undefined): void;\n delete(target: TreeID): void;\n has(target: TreeID): boolean;\n getNodeByID(target: TreeID): LoroTreeNode;\n subscribe(txn: Loro, listener: Listener): number;\n }\n\n interface LoroTreeNode<\n T extends Record<string, any> = Record<string, any>,\n > {\n readonly data: LoroMap<T>;\n createNode(): LoroTreeNode<T>;\n setAsRoot(): void;\n moveTo(parent: LoroTreeNode<T>): void;\n parent(): LoroTreeNode | undefined;\n children(): Array<LoroTreeNode<T>>;\n }\n}\n"],"names":[],"mappings":";;;;AAgBA,IAAK,CAAA,SAAA,CAAU,WAAc,GAAA,SAAA,GAAa,IAAM,EAAA;AAC9C,EAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAG,IAAI,CAAA,CAAA;AAC5B,CAAA,CAAA;AACA,IAAK,CAAA,SAAA,CAAU,YAAe,GAAA,SAAA,GAAa,IAAM,EAAA;AAC/C,EAAO,OAAA,IAAA,CAAK,OAAQ,CAAA,GAAG,IAAI,CAAA,CAAA;AAC7B,CAAA,CAAA;AACA,QAAA,CAAS,SAAU,CAAA,QAAA,GAAW,SAAU,IAAA,EAAM,KAAO,EAAA;AACnD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,KAAK,CAAA,CAAA;AAC5B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,aAAA,CAAc,KAAK,CAAG,EAAA;AACrD,IAAO,OAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,GAC7B,MAAA;AACL,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AACA,QAAS,CAAA,SAAA,CAAU,WAAc,GAAA,SAAA,GAAa,IAAM,EAAA;AAClD,EAAO,OAAA,IAAA,CAAK,MAAO,CAAA,GAAG,IAAI,CAAA,CAAA;AAC5B,CAAA,CAAA;AACA,OAAA,CAAQ,SAAU,CAAA,QAAA,GAAW,SAAU,IAAA,EAAM,GAAK,EAAA;AAChD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAC1B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,aAAA,CAAc,KAAK,CAAG,EAAA;AACrD,IAAO,OAAA,IAAA,CAAK,iBAAiB,KAAK,CAAA,CAAA;AAAA,GAC7B,MAAA;AACL,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AACA,OAAQ,CAAA,SAAA,CAAU,QAAW,GAAA,SAAA,GAAa,IAAM,EAAA;AAC9C,EAAO,OAAA,IAAA,CAAK,GAAI,CAAA,GAAG,IAAI,CAAA,CAAA;AACzB,CAAA,CAAA;AAkFA,MAAM,eAAkB,GAAA,CAAC,KAAO,EAAA,MAAA,EAAQ,QAAQ,MAAM,CAAA,CAAA;AAE/C,SAAS,cAAc,CAA6B,EAAA;AACzD,EAAO,OAAA,CAAA,CAAE,WAAW,MAAM,CAAA,CAAA;AAC5B,CAAA;AAoBO,SAAS,YAAY,KAAgC,EAAA;AAC1D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,KAAA,IAAS,IAAM,EAAA;AAC9C,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAM,MAAA,CAAA,GAAI,MAAO,CAAA,cAAA,CAAe,KAAK,CAAA,CAAA;AACrC,EAAI,IAAA,CAAA,IAAK,QAAQ,OAAO,CAAA,KAAM,YAAY,OAAO,CAAA,CAAE,MAAM,CAAA,KAAM,UAAY,EAAA;AACzE,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,OAAO,eAAgB,CAAA,QAAA,CAAS,KAAM,CAAA,IAAA,EAAM,CAAA,CAAA;AAC9C,CAAA;AAmBO,SAAS,QACd,KAKS,EAAA;AACT,EAAI,IAAA,WAAA,CAAY,KAAK,CAAG,EAAA;AACtB,IAAA,OAAO,MAAM,IAAK,EAAA,CAAA;AAAA,GACpB;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loro-crdt",
3
- "version": "0.12.0",
3
+ "version": "0.13.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",
@@ -17,7 +17,7 @@
17
17
  "homepage": "https://loro.dev",
18
18
  "license": "MIT",
19
19
  "dependencies": {
20
- "loro-wasm": "0.12.0"
20
+ "loro-wasm": "0.13.1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@rollup/plugin-node-resolve": "^15.0.1",
@@ -32,12 +32,12 @@
32
32
  "typescript": "^5.0.2",
33
33
  "vite": "^4.2.1",
34
34
  "vite-plugin-wasm": "^3.2.2",
35
- "vitest": "^1.0.4"
35
+ "vitest": "^1.4.0"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "rollup -c",
39
39
  "watch": "rollup -c -w",
40
- "test": "vitest run",
40
+ "test": "vitest run --typecheck",
41
41
  "prepublish": "pnpm run build"
42
42
  }
43
43
  }
package/src/index.ts CHANGED
@@ -1,17 +1,17 @@
1
1
  export * from "loro-wasm";
2
2
  import {
3
3
  Container,
4
+ ContainerID,
4
5
  Delta,
6
+ Loro,
7
+ LoroList,
8
+ LoroMap,
5
9
  LoroText,
6
10
  LoroTree,
7
11
  LoroTreeNode,
8
12
  OpId,
9
- Value,
10
- ContainerID,
11
- Loro,
12
- LoroList,
13
- LoroMap,
14
13
  TreeID,
14
+ Value,
15
15
  } from "loro-wasm";
16
16
 
17
17
  Loro.prototype.getTypedMap = function (...args) {
@@ -179,17 +179,13 @@ export function isContainer(value: any): value is Container {
179
179
  */
180
180
  export function getType<T>(
181
181
  value: T,
182
- ): T extends LoroText
183
- ? "Text"
184
- : T extends LoroMap
185
- ? "Map"
186
- : T extends LoroTree
187
- ? "Tree"
188
- : T extends LoroList
189
- ? "List"
182
+ ): T extends LoroText ? "Text"
183
+ : T extends LoroMap<any> ? "Map"
184
+ : T extends LoroTree<any> ? "Tree"
185
+ : T extends LoroList<any> ? "List"
190
186
  : "Json" {
191
187
  if (isContainer(value)) {
192
- return value.kind();
188
+ return value.kind() as unknown as any;
193
189
  }
194
190
 
195
191
  return "Json" as any;
@@ -207,36 +203,41 @@ declare module "loro-wasm" {
207
203
  getTypedList<Key extends keyof T & string>(
208
204
  name: Key,
209
205
  ): T[Key] extends LoroList ? T[Key] : never;
206
+ getMap(key: string | ContainerID): LoroMap<T[string]>;
207
+ getList(key: string | ContainerID): LoroList<T[string]>;
208
+ getTree(key: string | ContainerID): LoroTree<T[string]>;
209
+ getText(key: string | ContainerID): LoroText;
210
210
  }
211
211
 
212
- interface LoroList<T extends any[] = any[]> {
213
- insertContainer(pos: number, container: "Map"): LoroMap;
214
- insertContainer(pos: number, container: "List"): LoroList;
215
- insertContainer(pos: number, container: "Text"): LoroText;
216
- insertContainer(pos: number, container: "Tree"): LoroTree;
217
- insertContainer(pos: number, container: string): never;
218
-
212
+ interface LoroList<
213
+ T extends any[] = any[],
214
+ > {
215
+ new (): LoroList<T>;
216
+ insertContainer<C extends Container>(
217
+ pos: number,
218
+ child: C,
219
+ ): C;
219
220
  get(index: number): undefined | Value | Container;
220
221
  getTyped<Key extends keyof T & number>(loro: Loro, index: Key): T[Key];
221
222
  insertTyped<Key extends keyof T & number>(pos: Key, value: T[Key]): void;
222
223
  insert(pos: number, value: Value): void;
223
224
  delete(pos: number, len: number): void;
224
225
  subscribe(txn: Loro, listener: Listener): number;
226
+ getAttached(): undefined | LoroList<T>;
225
227
  }
226
228
 
227
- interface LoroMap<T extends Record<string, any> = Record<string, any>> {
228
- getOrCreateContainer(key: string, container_type: "Map"): LoroMap;
229
- getOrCreateContainer(key: string, container_type: "List"): LoroList;
230
- getOrCreateContainer(key: string, container_type: "Text"): LoroText;
231
- getOrCreateContainer(key: string, container_type: "Tree"): LoroTree;
232
- getOrCreateContainer(key: string, container_type: string): never;
233
-
234
- setContainer(key: string, container_type: "Map"): LoroMap;
235
- setContainer(key: string, container_type: "List"): LoroList;
236
- setContainer(key: string, container_type: "Text"): LoroText;
237
- setContainer(key: string, container_type: "Tree"): LoroTree;
238
- setContainer(key: string, container_type: string): never;
239
-
229
+ interface LoroMap<
230
+ T extends Record<string, any> = Record<string, any>,
231
+ > {
232
+ new (): LoroMap<T>;
233
+ getOrCreateContainer<C extends Container>(
234
+ key: string,
235
+ child: C,
236
+ ): C;
237
+ setContainer<C extends Container>(
238
+ key: string,
239
+ child: C,
240
+ ): C;
240
241
  get(key: string): undefined | Value | Container;
241
242
  getTyped<Key extends keyof T & string>(txn: Loro, key: Key): T[Key];
242
243
  set(key: string, value: Value): void;
@@ -246,13 +247,17 @@ declare module "loro-wasm" {
246
247
  }
247
248
 
248
249
  interface LoroText {
250
+ new (): LoroText;
249
251
  insert(pos: number, text: string): void;
250
252
  delete(pos: number, len: number): void;
251
253
  subscribe(txn: Loro, listener: Listener): number;
252
254
  }
253
255
 
254
- interface LoroTree {
255
- createNode(parent: TreeID | undefined): LoroTreeNode;
256
+ interface LoroTree<
257
+ T extends Record<string, any> = Record<string, any>,
258
+ > {
259
+ new (): LoroTree<T>;
260
+ createNode(parent: TreeID | undefined): LoroTreeNode<T>;
256
261
  move(target: TreeID, parent: TreeID | undefined): void;
257
262
  delete(target: TreeID): void;
258
263
  has(target: TreeID): boolean;
@@ -260,12 +265,14 @@ declare module "loro-wasm" {
260
265
  subscribe(txn: Loro, listener: Listener): number;
261
266
  }
262
267
 
263
- interface LoroTreeNode {
264
- readonly data: LoroMap;
265
- createNode(): LoroTreeNode;
268
+ interface LoroTreeNode<
269
+ T extends Record<string, any> = Record<string, any>,
270
+ > {
271
+ readonly data: LoroMap<T>;
272
+ createNode(): LoroTreeNode<T>;
266
273
  setAsRoot(): void;
267
- moveTo(parent: LoroTreeNode): void;
274
+ moveTo(parent: LoroTreeNode<T>): void;
268
275
  parent(): LoroTreeNode | undefined;
269
- children(): Array<LoroTreeNode>;
276
+ children(): Array<LoroTreeNode<T>>;
270
277
  }
271
278
  }
package/tsconfig.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  /* Visit https://aka.ms/tsconfig to read more about this file */
4
-
5
4
  /* Projects */
6
5
  // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7
6
  // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
@@ -9,7 +8,6 @@
9
8
  // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10
9
  // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11
10
  // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12
-
13
11
  /* Language and Environment */
14
12
  "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
15
13
  // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
@@ -23,7 +21,6 @@
23
21
  // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24
22
  // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25
23
  // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26
-
27
24
  /* Modules */
28
25
  "module": "commonjs" /* Specify what module code is generated. */,
29
26
  // "rootDir": "./", /* Specify the root folder within your source files. */
@@ -42,12 +39,10 @@
42
39
  // "resolveJsonModule": true, /* Enable importing .json files. */
43
40
  // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44
41
  // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
45
-
46
42
  /* JavaScript Support */
47
43
  // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48
44
  // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49
45
  // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50
-
51
46
  /* Emit */
52
47
  // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53
48
  // "declarationMap": true, /* Create sourcemaps for d.ts files. */
@@ -55,7 +50,7 @@
55
50
  // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56
51
  // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57
52
  // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58
- // "outDir": "./", /* Specify an output folder for all emitted files. */
53
+ "outDir": "./dist", /* Specify an output folder for all emitted files. */
59
54
  // "removeComments": true, /* Disable emitting comments. */
60
55
  // "noEmit": true, /* Disable emitting files from a compilation. */
61
56
  // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
@@ -72,7 +67,6 @@
72
67
  // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73
68
  // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74
69
  // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75
-
76
70
  /* Interop Constraints */
77
71
  // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78
72
  // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
@@ -80,7 +74,6 @@
80
74
  "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
81
75
  // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82
76
  "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
83
-
84
77
  /* Type Checking */
85
78
  "strict": true /* Enable all strict type-checking options. */,
86
79
  // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
@@ -101,7 +94,6 @@
101
94
  // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102
95
  // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103
96
  // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104
-
105
97
  /* Completeness */
106
98
  // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107
99
  "skipLibCheck": true /* Skip type checking all .d.ts files. */