@loro-extended/change 0.9.0 → 0.9.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/dist/index.d.ts +9 -4
- package/dist/index.js +215 -187
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/conversion.test.ts +72 -72
- package/src/conversion.ts +5 -5
- package/src/overlay-recursion.test.ts +325 -0
- package/src/overlay.ts +45 -8
- package/src/typed-refs/base.ts +10 -0
- package/src/typed-refs/counter.ts +2 -2
- package/src/typed-refs/doc.ts +17 -24
- package/src/typed-refs/list-base.ts +42 -18
- package/src/typed-refs/map.ts +38 -65
- package/src/typed-refs/movable-list.ts +2 -2
- package/src/typed-refs/record.test.ts +9 -9
- package/src/typed-refs/record.ts +56 -69
- package/src/typed-refs/text.ts +6 -6
- package/src/typed-refs/tree.ts +3 -3
- package/src/typed-refs/utils.ts +93 -8
package/src/typed-refs/utils.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LoroCounter,
|
|
3
|
+
LoroList,
|
|
4
|
+
LoroMap,
|
|
5
|
+
LoroMovableList,
|
|
6
|
+
LoroText,
|
|
7
|
+
LoroTree,
|
|
8
|
+
type Value,
|
|
9
|
+
} from "loro-crdt"
|
|
1
10
|
import type {
|
|
2
11
|
ContainerShape,
|
|
3
12
|
CounterContainerShape,
|
|
@@ -8,7 +17,7 @@ import type {
|
|
|
8
17
|
TextContainerShape,
|
|
9
18
|
TreeContainerShape,
|
|
10
19
|
} from "../shape.js"
|
|
11
|
-
import
|
|
20
|
+
import { TypedRef, type TypedRefParams } from "./base.js"
|
|
12
21
|
import { CounterRef } from "./counter.js"
|
|
13
22
|
import { ListRef } from "./list.js"
|
|
14
23
|
import { MapRef } from "./map.js"
|
|
@@ -22,6 +31,82 @@ import { RecordRef } from "./record.js"
|
|
|
22
31
|
import { TextRef } from "./text.js"
|
|
23
32
|
import { TreeRef } from "./tree.js"
|
|
24
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Mapping from container shape types to their Loro constructor classes.
|
|
36
|
+
* Used when creating new containers via getOrCreateContainer().
|
|
37
|
+
*/
|
|
38
|
+
export const containerConstructor = {
|
|
39
|
+
counter: LoroCounter,
|
|
40
|
+
list: LoroList,
|
|
41
|
+
map: LoroMap,
|
|
42
|
+
movableList: LoroMovableList,
|
|
43
|
+
record: LoroMap, // Records use LoroMap as their underlying container
|
|
44
|
+
text: LoroText,
|
|
45
|
+
tree: LoroTree,
|
|
46
|
+
} as const
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Unwraps a TypedRef to its primitive value for readonly access.
|
|
50
|
+
* Counter refs return their numeric value, Text refs return their string.
|
|
51
|
+
* Other container types are returned as-is.
|
|
52
|
+
*/
|
|
53
|
+
export function unwrapReadonlyPrimitive(
|
|
54
|
+
ref: TypedRef<any>,
|
|
55
|
+
shape: ContainerShape,
|
|
56
|
+
): any {
|
|
57
|
+
if (shape._type === "counter") {
|
|
58
|
+
return (ref as any).value
|
|
59
|
+
}
|
|
60
|
+
if (shape._type === "text") {
|
|
61
|
+
return (ref as any).toString()
|
|
62
|
+
}
|
|
63
|
+
return ref
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Absorbs cached plain values back into a LoroMap container.
|
|
68
|
+
* For TypedRef entries, recursively calls absorbPlainValues().
|
|
69
|
+
* For plain Value entries, sets them directly on the container.
|
|
70
|
+
*/
|
|
71
|
+
export function absorbCachedPlainValues(
|
|
72
|
+
cache: Map<string, TypedRef<ContainerShape> | Value>,
|
|
73
|
+
getContainer: () => LoroMap,
|
|
74
|
+
): void {
|
|
75
|
+
let container: LoroMap | undefined
|
|
76
|
+
|
|
77
|
+
for (const [key, ref] of cache.entries()) {
|
|
78
|
+
if (ref instanceof TypedRef) {
|
|
79
|
+
// Contains a TypedRef, not a plain Value: keep recursing
|
|
80
|
+
ref.absorbPlainValues()
|
|
81
|
+
} else {
|
|
82
|
+
// Plain value!
|
|
83
|
+
if (!container) container = getContainer()
|
|
84
|
+
container.set(key, ref)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Serializes a TypedRef to JSON by iterating over its keys.
|
|
91
|
+
* For nested TypedRefs with toJSON(), calls their toJSON method.
|
|
92
|
+
* For plain values, includes them directly.
|
|
93
|
+
*/
|
|
94
|
+
export function serializeRefToJSON(
|
|
95
|
+
ref: Record<string, any>,
|
|
96
|
+
keys: Iterable<string>,
|
|
97
|
+
): Record<string, any> {
|
|
98
|
+
const result: Record<string, any> = {}
|
|
99
|
+
for (const key of keys) {
|
|
100
|
+
const value = ref[key]
|
|
101
|
+
if (value && typeof value === "object" && "toJSON" in value) {
|
|
102
|
+
result[key] = value.toJSON()
|
|
103
|
+
} else {
|
|
104
|
+
result[key] = value
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return result
|
|
108
|
+
}
|
|
109
|
+
|
|
25
110
|
// Generic catch-all overload
|
|
26
111
|
export function createContainerTypedRef<T extends ContainerShape>(
|
|
27
112
|
params: TypedRefParams<T>,
|
|
@@ -63,26 +148,26 @@ export function createContainerTypedRef(
|
|
|
63
148
|
}
|
|
64
149
|
|
|
65
150
|
export function assignPlainValueToTypedRef(
|
|
66
|
-
|
|
151
|
+
ref: TypedRef<any>,
|
|
67
152
|
value: any,
|
|
68
153
|
): boolean {
|
|
69
|
-
const shapeType = (
|
|
154
|
+
const shapeType = (ref as any).shape._type
|
|
70
155
|
|
|
71
156
|
if (shapeType === "map" || shapeType === "record") {
|
|
72
157
|
for (const k in value) {
|
|
73
|
-
;(
|
|
158
|
+
;(ref as any)[k] = value[k]
|
|
74
159
|
}
|
|
75
160
|
return true
|
|
76
161
|
}
|
|
77
162
|
|
|
78
163
|
if (shapeType === "list" || shapeType === "movableList") {
|
|
79
164
|
if (Array.isArray(value)) {
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
82
|
-
|
|
165
|
+
const listRef = ref as any
|
|
166
|
+
if (listRef.length > 0) {
|
|
167
|
+
listRef.delete(0, listRef.length)
|
|
83
168
|
}
|
|
84
169
|
for (const item of value) {
|
|
85
|
-
|
|
170
|
+
listRef.push(item)
|
|
86
171
|
}
|
|
87
172
|
return true
|
|
88
173
|
}
|