loro-crdt 0.6.1 → 0.6.2

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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Refine getType and isContainer
8
+
3
9
  ## 0.6.1
4
10
 
5
11
  ### Patch Changes
package/dist/loro.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Value, Container, TreeID, PrelimList, PrelimMap, PrelimText, OpId, ContainerID, Delta, ContainerType } from 'loro-wasm';
1
+ import { Value, Container, TreeID, PrelimList, PrelimMap, PrelimText, OpId, ContainerID, Delta, LoroText, LoroMap, LoroTree, LoroList } from 'loro-wasm';
2
2
  export * from 'loro-wasm';
3
3
  export { Loro } from 'loro-wasm';
4
4
 
@@ -67,8 +67,41 @@ interface Listener {
67
67
  }
68
68
  declare function isContainerId(s: string): s is ContainerID;
69
69
 
70
+ /** Whether the value is a container.
71
+ *
72
+ * # Example
73
+ *
74
+ * ```ts
75
+ * const doc = new Loro();
76
+ * const map = doc.getMap("map");
77
+ * const list = doc.getList("list");
78
+ * const text = doc.getText("text");
79
+ * isContainer(map); // true
80
+ * isContainer(list); // true
81
+ * isContainer(text); // true
82
+ * isContainer(123); // false
83
+ * isContainer("123"); // false
84
+ * isContainer({}); // false
85
+ */
70
86
  declare function isContainer(value: any): value is Container;
71
- declare function valueType(value: any): "Json" | ContainerType;
87
+ /** Get the type of a value that may be a container.
88
+ *
89
+ * # Example
90
+ *
91
+ * ```ts
92
+ * const doc = new Loro();
93
+ * const map = doc.getMap("map");
94
+ * const list = doc.getList("list");
95
+ * const text = doc.getText("text");
96
+ * getType(map); // "Map"
97
+ * getType(list); // "List"
98
+ * getType(text); // "Text"
99
+ * getType(123); // "Json"
100
+ * getType("123"); // "Json"
101
+ * getType({}); // "Json"
102
+ * ```
103
+ */
104
+ declare function getType<T>(value: T): T extends LoroText ? "Text" : T extends LoroMap ? "Map" : T extends LoroTree ? "Tree" : T extends LoroList ? "List" : "Json";
72
105
  declare module "loro-wasm" {
73
106
  interface Loro {
74
107
  subscribe(listener: Listener): number;
@@ -119,4 +152,4 @@ declare module "loro-wasm" {
119
152
  }
120
153
  }
121
154
 
122
- export { Diff, Frontiers, ListDiff, LoroEvent, MapDiff, Path, Prelim, TextDiff, TreeDiff, isContainer, isContainerId, valueType };
155
+ export { Diff, Frontiers, ListDiff, LoroEvent, MapDiff, Path, Prelim, TextDiff, TreeDiff, getType, isContainer, isContainerId };
package/dist/loro.js CHANGED
@@ -39,9 +39,12 @@ function isContainer(value) {
39
39
  return false;
40
40
  }
41
41
  const p = value.__proto__;
42
- return p.hasOwnProperty("kind") && CONTAINER_TYPES.includes(value.kind());
42
+ if (p == null || typeof p !== "object" || typeof p["kind"] !== "function") {
43
+ return false;
44
+ }
45
+ return CONTAINER_TYPES.includes(value.kind());
43
46
  }
44
- function valueType(value) {
47
+ function getType(value) {
45
48
  if (isContainer(value)) {
46
49
  return value.kind();
47
50
  }
@@ -52,9 +55,9 @@ Object.defineProperty(exports, 'Loro', {
52
55
  enumerable: true,
53
56
  get: function () { return loroWasm.Loro; }
54
57
  });
58
+ exports.getType = getType;
55
59
  exports.isContainer = isContainer;
56
60
  exports.isContainerId = isContainerId;
57
- exports.valueType = valueType;
58
61
  Object.keys(loroWasm).forEach(function (k) {
59
62
  if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
60
63
  enumerable: true,
package/dist/loro.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"loro.js","sources":["../src/index.ts"],"sourcesContent":["export * from \"loro-wasm\";\nimport { Container, ContainerType, Delta, OpId, Value } from \"loro-wasm\";\nimport { PrelimText, PrelimList, PrelimMap } from \"loro-wasm\";\nimport { ContainerID, Loro, LoroList, LoroMap, TreeID } 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 Prelim = PrelimList | PrelimMap | PrelimText;\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) and strings\n * (e.g., keys of a map container), indicating the absolute position of the event's source\n * within a loro document.\n */\nexport type Path = (number | string)[];\n\n/**\n * The event of Loro.\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 LoroEvent {\n /**\n * The unique ID of the event.\n */\n id: bigint;\n local: boolean;\n origin?: string;\n /**\n * If true, this event was triggered by a child container.\n */\n fromChildren: boolean;\n /**\n * If true, this event was triggered by a checkout.\n */\n fromCheckout: boolean;\n diff: Diff;\n target: ContainerID;\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 TreeDiff = {\n type: \"tree\";\n diff:\n | { target: TreeID; action: \"create\" | \"delete\" }\n | { target: TreeID; action: \"move\"; parent: TreeID };\n};\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;\n\ninterface Listener {\n (event: LoroEvent): 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\nexport function isContainer(value: any): value is Container {\n if (typeof value !== \"object\" || value == null) {\n return false;\n }\n\n const p = value.__proto__;\n return p.hasOwnProperty(\"kind\") && CONTAINER_TYPES.includes(value.kind());\n}\n\nexport function valueType(value: any): \"Json\" | ContainerType {\n if (isContainer(value)) {\n return value.kind();\n }\n\n return \"Json\";\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 | Prelim): 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 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 | Prelim): 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 create(parent: TreeID | undefined): TreeID;\n mov(target: TreeID, parent: TreeID | undefined): void;\n delete(target: TreeID): void;\n getMeta(target: TreeID): LoroMap;\n parent(target: TreeID): TreeID | undefined;\n contains(target: TreeID): boolean;\n subscribe(txn: Loro, listener: Listener): number;\n }\n}\n"],"names":["Loro","LoroList","LoroMap"],"mappings":";;;;AAKAA,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;AAqEA,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;AAIO,SAAS,YAAY,KAAgC,EAAA;AAC1D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,KAAA,IAAS,IAAM,EAAA;AAC9C,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,IAAI,KAAM,CAAA,SAAA,CAAA;AAChB,EAAO,OAAA,CAAA,CAAE,eAAe,MAAM,CAAA,IAAK,gBAAgB,QAAS,CAAA,KAAA,CAAM,MAAM,CAAA,CAAA;AAC1E,CAAA;AAEO,SAAS,UAAU,KAAoC,EAAA;AAC5D,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 { Container, ContainerType, Delta, LoroText, LoroTree, OpId, Value } from \"loro-wasm\";\nimport { PrelimText, PrelimList, PrelimMap } from \"loro-wasm\";\nimport { ContainerID, Loro, LoroList, LoroMap, TreeID } 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 Prelim = PrelimList | PrelimMap | PrelimText;\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) and strings\n * (e.g., keys of a map container), indicating the absolute position of the event's source\n * within a loro document.\n */\nexport type Path = (number | string)[];\n\n/**\n * The event of Loro.\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 LoroEvent {\n /**\n * The unique ID of the event.\n */\n id: bigint;\n local: boolean;\n origin?: string;\n /**\n * If true, this event was triggered by a child container.\n */\n fromChildren: boolean;\n /**\n * If true, this event was triggered by a checkout.\n */\n fromCheckout: boolean;\n diff: Diff;\n target: ContainerID;\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 TreeDiff = {\n type: \"tree\";\n diff:\n | { target: TreeID; action: \"create\" | \"delete\" }\n | { target: TreeID; action: \"move\"; parent: TreeID };\n};\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;\n\ninterface Listener {\n (event: LoroEvent): 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 = value.__proto__;\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>(value: T): T extends LoroText ? \"Text\" :\n T extends LoroMap ? \"Map\" :\n T extends LoroTree ? \"Tree\" :\n T extends LoroList ? \"List\" : \"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 | Prelim): 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 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 | Prelim): 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 create(parent: TreeID | undefined): TreeID;\n mov(target: TreeID, parent: TreeID | undefined): void;\n delete(target: TreeID): void;\n getMeta(target: TreeID): LoroMap;\n parent(target: TreeID): TreeID | undefined;\n contains(target: TreeID): boolean;\n subscribe(txn: Loro, listener: Listener): number;\n }\n}\n"],"names":["Loro","LoroList","LoroMap"],"mappings":";;;;AAKAA,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;AAqEA,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,EAAA,MAAM,IAAI,KAAM,CAAA,SAAA,CAAA;AAChB,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,QAAW,KAGY,EAAA;AACrC,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 CHANGED
@@ -39,14 +39,17 @@ function isContainer(value) {
39
39
  return false;
40
40
  }
41
41
  const p = value.__proto__;
42
- return p.hasOwnProperty("kind") && CONTAINER_TYPES.includes(value.kind());
42
+ if (p == null || typeof p !== "object" || typeof p["kind"] !== "function") {
43
+ return false;
44
+ }
45
+ return CONTAINER_TYPES.includes(value.kind());
43
46
  }
44
- function valueType(value) {
47
+ function getType(value) {
45
48
  if (isContainer(value)) {
46
49
  return value.kind();
47
50
  }
48
51
  return "Json";
49
52
  }
50
53
 
51
- export { isContainer, isContainerId, valueType };
54
+ export { getType, isContainer, isContainerId };
52
55
  //# sourceMappingURL=loro.mjs.map
package/dist/loro.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"loro.mjs","sources":["../src/index.ts"],"sourcesContent":["export * from \"loro-wasm\";\nimport { Container, ContainerType, Delta, OpId, Value } from \"loro-wasm\";\nimport { PrelimText, PrelimList, PrelimMap } from \"loro-wasm\";\nimport { ContainerID, Loro, LoroList, LoroMap, TreeID } 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 Prelim = PrelimList | PrelimMap | PrelimText;\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) and strings\n * (e.g., keys of a map container), indicating the absolute position of the event's source\n * within a loro document.\n */\nexport type Path = (number | string)[];\n\n/**\n * The event of Loro.\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 LoroEvent {\n /**\n * The unique ID of the event.\n */\n id: bigint;\n local: boolean;\n origin?: string;\n /**\n * If true, this event was triggered by a child container.\n */\n fromChildren: boolean;\n /**\n * If true, this event was triggered by a checkout.\n */\n fromCheckout: boolean;\n diff: Diff;\n target: ContainerID;\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 TreeDiff = {\n type: \"tree\";\n diff:\n | { target: TreeID; action: \"create\" | \"delete\" }\n | { target: TreeID; action: \"move\"; parent: TreeID };\n};\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;\n\ninterface Listener {\n (event: LoroEvent): 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\nexport function isContainer(value: any): value is Container {\n if (typeof value !== \"object\" || value == null) {\n return false;\n }\n\n const p = value.__proto__;\n return p.hasOwnProperty(\"kind\") && CONTAINER_TYPES.includes(value.kind());\n}\n\nexport function valueType(value: any): \"Json\" | ContainerType {\n if (isContainer(value)) {\n return value.kind();\n }\n\n return \"Json\";\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 | Prelim): 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 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 | Prelim): 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 create(parent: TreeID | undefined): TreeID;\n mov(target: TreeID, parent: TreeID | undefined): void;\n delete(target: TreeID): void;\n getMeta(target: TreeID): LoroMap;\n parent(target: TreeID): TreeID | undefined;\n contains(target: TreeID): boolean;\n subscribe(txn: Loro, listener: Listener): number;\n }\n}\n"],"names":[],"mappings":";;;;AAKA,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;AAqEA,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;AAIO,SAAS,YAAY,KAAgC,EAAA;AAC1D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAY,IAAA,KAAA,IAAS,IAAM,EAAA;AAC9C,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,IAAI,KAAM,CAAA,SAAA,CAAA;AAChB,EAAO,OAAA,CAAA,CAAE,eAAe,MAAM,CAAA,IAAK,gBAAgB,QAAS,CAAA,KAAA,CAAM,MAAM,CAAA,CAAA;AAC1E,CAAA;AAEO,SAAS,UAAU,KAAoC,EAAA;AAC5D,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 { Container, ContainerType, Delta, LoroText, LoroTree, OpId, Value } from \"loro-wasm\";\nimport { PrelimText, PrelimList, PrelimMap } from \"loro-wasm\";\nimport { ContainerID, Loro, LoroList, LoroMap, TreeID } 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 Prelim = PrelimList | PrelimMap | PrelimText;\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) and strings\n * (e.g., keys of a map container), indicating the absolute position of the event's source\n * within a loro document.\n */\nexport type Path = (number | string)[];\n\n/**\n * The event of Loro.\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 LoroEvent {\n /**\n * The unique ID of the event.\n */\n id: bigint;\n local: boolean;\n origin?: string;\n /**\n * If true, this event was triggered by a child container.\n */\n fromChildren: boolean;\n /**\n * If true, this event was triggered by a checkout.\n */\n fromCheckout: boolean;\n diff: Diff;\n target: ContainerID;\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 TreeDiff = {\n type: \"tree\";\n diff:\n | { target: TreeID; action: \"create\" | \"delete\" }\n | { target: TreeID; action: \"move\"; parent: TreeID };\n};\n\nexport type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;\n\ninterface Listener {\n (event: LoroEvent): 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 = value.__proto__;\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>(value: T): T extends LoroText ? \"Text\" :\n T extends LoroMap ? \"Map\" :\n T extends LoroTree ? \"Tree\" :\n T extends LoroList ? \"List\" : \"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 | Prelim): 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 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 | Prelim): 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 create(parent: TreeID | undefined): TreeID;\n mov(target: TreeID, parent: TreeID | undefined): void;\n delete(target: TreeID): void;\n getMeta(target: TreeID): LoroMap;\n parent(target: TreeID): TreeID | undefined;\n contains(target: TreeID): boolean;\n subscribe(txn: Loro, listener: Listener): number;\n }\n}\n"],"names":[],"mappings":";;;;AAKA,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;AAqEA,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,EAAA,MAAM,IAAI,KAAM,CAAA,SAAA,CAAA;AAChB,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,QAAW,KAGY,EAAA;AACrC,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.6.1",
3
+ "version": "0.6.2",
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",
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from "loro-wasm";
2
- import { Container, ContainerType, Delta, OpId, Value } from "loro-wasm";
2
+ import { Container, ContainerType, Delta, LoroText, LoroTree, OpId, Value } from "loro-wasm";
3
3
  import { PrelimText, PrelimList, PrelimMap } from "loro-wasm";
4
4
  import { ContainerID, Loro, LoroList, LoroMap, TreeID } from "loro-wasm";
5
5
 
@@ -89,8 +89,8 @@ export type MapDiff = {
89
89
  export type TreeDiff = {
90
90
  type: "tree";
91
91
  diff:
92
- | { target: TreeID; action: "create" | "delete" }
93
- | { target: TreeID; action: "move"; parent: TreeID };
92
+ | { target: TreeID; action: "create" | "delete" }
93
+ | { target: TreeID; action: "move"; parent: TreeID };
94
94
  };
95
95
 
96
96
  export type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;
@@ -107,21 +107,61 @@ export function isContainerId(s: string): s is ContainerID {
107
107
 
108
108
  export { Loro };
109
109
 
110
+ /** Whether the value is a container.
111
+ *
112
+ * # Example
113
+ *
114
+ * ```ts
115
+ * const doc = new Loro();
116
+ * const map = doc.getMap("map");
117
+ * const list = doc.getList("list");
118
+ * const text = doc.getText("text");
119
+ * isContainer(map); // true
120
+ * isContainer(list); // true
121
+ * isContainer(text); // true
122
+ * isContainer(123); // false
123
+ * isContainer("123"); // false
124
+ * isContainer({}); // false
125
+ */
110
126
  export function isContainer(value: any): value is Container {
111
127
  if (typeof value !== "object" || value == null) {
112
128
  return false;
113
129
  }
114
130
 
115
131
  const p = value.__proto__;
116
- return p.hasOwnProperty("kind") && CONTAINER_TYPES.includes(value.kind());
132
+ if (p == null || typeof p !== "object" || typeof p["kind"] !== "function") {
133
+ return false;
134
+ }
135
+
136
+ return CONTAINER_TYPES.includes(value.kind());
117
137
  }
118
138
 
119
- export function valueType(value: any): "Json" | ContainerType {
139
+ /** Get the type of a value that may be a container.
140
+ *
141
+ * # Example
142
+ *
143
+ * ```ts
144
+ * const doc = new Loro();
145
+ * const map = doc.getMap("map");
146
+ * const list = doc.getList("list");
147
+ * const text = doc.getText("text");
148
+ * getType(map); // "Map"
149
+ * getType(list); // "List"
150
+ * getType(text); // "Text"
151
+ * getType(123); // "Json"
152
+ * getType("123"); // "Json"
153
+ * getType({}); // "Json"
154
+ * ```
155
+ */
156
+ export function getType<T>(value: T): T extends LoroText ? "Text" :
157
+ T extends LoroMap ? "Map" :
158
+ T extends LoroTree ? "Tree" :
159
+ T extends LoroList ? "List" : "Json" {
120
160
  if (isContainer(value)) {
121
161
  return value.kind();
122
162
  }
123
163
 
124
- return "Json";
164
+ return "Json" as any;
125
165
  }
126
166
 
127
167
  declare module "loro-wasm" {