mobx-keystone-yjs 1.4.0 → 1.5.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 +33 -25
- package/dist/mobx-keystone-yjs.esm.js +33 -30
- package/dist/mobx-keystone-yjs.esm.mjs +33 -30
- package/dist/mobx-keystone-yjs.umd.js +33 -30
- package/dist/types/binding/bindYjsToMobxKeystone.d.ts +1 -1
- package/dist/types/binding/convertJsonToYjsData.d.ts +5 -4
- package/dist/types/binding/convertYjsDataToJson.d.ts +3 -2
- package/dist/types/binding/yjsBindingContext.d.ts +1 -1
- package/dist/types/jsonTypes.d.ts +5 -5
- package/package.json +91 -91
- package/src/binding/YjsTextModel.ts +248 -249
- package/src/binding/applyMobxKeystonePatchToYjsObject.ts +98 -96
- package/src/binding/bindYjsToMobxKeystone.ts +192 -191
- package/src/binding/convertJsonToYjsData.ts +78 -72
- package/src/binding/convertYjsDataToJson.ts +31 -31
- package/src/binding/convertYjsEventToPatches.ts +96 -92
- package/src/binding/resolveYjsPath.ts +27 -27
- package/src/binding/yjsBindingContext.ts +42 -42
- package/src/jsonTypes.ts +9 -4
- package/src/utils/getOrCreateYjsCollectionAtom.ts +27 -18
|
@@ -1,72 +1,78 @@
|
|
|
1
|
-
import * as Y from "yjs"
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
1
|
+
import * as Y from "yjs"
|
|
2
|
+
import { YjsTextModel, yjsTextModelId } from "./YjsTextModel"
|
|
3
|
+
import { SnapshotOutOf } from "mobx-keystone"
|
|
4
|
+
import { YjsData } from "./convertYjsDataToJson"
|
|
5
|
+
import {
|
|
6
|
+
JsonArrayWithUndefined,
|
|
7
|
+
JsonObjectWithUndefined,
|
|
8
|
+
JsonPrimitiveWithUndefined,
|
|
9
|
+
JsonValueWithUndefined,
|
|
10
|
+
} from "../jsonTypes"
|
|
11
|
+
|
|
12
|
+
function isJsonPrimitiveWithUndefined(v: JsonValueWithUndefined): v is JsonPrimitiveWithUndefined {
|
|
13
|
+
const t = typeof v
|
|
14
|
+
return t === "string" || t === "number" || t === "boolean" || v === null || v === undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isJsonArrayWithUndefined(v: JsonValueWithUndefined): v is JsonArrayWithUndefined {
|
|
18
|
+
return Array.isArray(v)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isJsonObjectWithUndefined(v: JsonValueWithUndefined): v is JsonObjectWithUndefined {
|
|
22
|
+
return !isJsonArrayWithUndefined(v) && typeof v === "object"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Converts a JSON value to a Y.js data structure.
|
|
27
|
+
* Objects are converted to Y.Maps, arrays to Y.Arrays, primitives are untouched.
|
|
28
|
+
* Frozen values are a special case and they are kept as immutable plain values.
|
|
29
|
+
*/
|
|
30
|
+
export function convertJsonToYjsData(v: JsonValueWithUndefined | undefined): YjsData {
|
|
31
|
+
if (v === undefined || isJsonPrimitiveWithUndefined(v)) {
|
|
32
|
+
return v
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (isJsonArrayWithUndefined(v)) {
|
|
36
|
+
const arr = new Y.Array()
|
|
37
|
+
applyJsonArrayToYArray(arr, v)
|
|
38
|
+
return arr as YjsData
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isJsonObjectWithUndefined(v)) {
|
|
42
|
+
if (v.$frozen === true) {
|
|
43
|
+
// frozen value, save as immutable object
|
|
44
|
+
return v
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (v.$modelType === yjsTextModelId) {
|
|
48
|
+
const text = new Y.Text()
|
|
49
|
+
const yjsTextModel = v as unknown as SnapshotOutOf<YjsTextModel>
|
|
50
|
+
yjsTextModel.deltaList.forEach((frozenDeltas) => {
|
|
51
|
+
text.applyDelta(frozenDeltas.data)
|
|
52
|
+
})
|
|
53
|
+
return text
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const map = new Y.Map()
|
|
57
|
+
applyJsonObjectToYMap(map, v)
|
|
58
|
+
return map as YjsData
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
throw new Error(`unsupported value type: ${v}`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Applies a JSON array to a Y.Array, using the convertJsonToYjsData to convert the values.
|
|
66
|
+
*/
|
|
67
|
+
export function applyJsonArrayToYArray(dest: Y.Array<unknown>, source: JsonArrayWithUndefined) {
|
|
68
|
+
dest.push(source.map(convertJsonToYjsData))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Applies a JSON object to a Y.Map, using the convertJsonToYjsData to convert the values.
|
|
73
|
+
*/
|
|
74
|
+
export function applyJsonObjectToYMap(dest: Y.Map<unknown>, source: JsonObjectWithUndefined) {
|
|
75
|
+
Object.entries(source).forEach(([k, v]) => {
|
|
76
|
+
dest.set(k, convertJsonToYjsData(v))
|
|
77
|
+
})
|
|
78
|
+
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { modelSnapshotOutWithMetadata } from "mobx-keystone"
|
|
2
|
-
import * as Y from "yjs"
|
|
3
|
-
import {
|
|
4
|
-
import { YjsTextModel } from "./YjsTextModel"
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
):
|
|
9
|
-
if (yjsData instanceof Y.Array) {
|
|
10
|
-
return yjsData.map((v) => convertYjsDataToJson(v))
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
if (yjsData instanceof Y.Map) {
|
|
14
|
-
const obj:
|
|
15
|
-
yjsData.forEach((v, k) => {
|
|
16
|
-
obj[k] = convertYjsDataToJson(v)
|
|
17
|
-
})
|
|
18
|
-
return obj
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (yjsData instanceof Y.Text) {
|
|
22
|
-
const deltas = yjsData.toDelta()
|
|
23
|
-
|
|
24
|
-
return modelSnapshotOutWithMetadata(YjsTextModel, {
|
|
25
|
-
deltaList: deltas.length > 0 ? [{ $frozen: true, data: deltas }] : [],
|
|
26
|
-
}) as
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// assume it's a primitive
|
|
30
|
-
return yjsData
|
|
31
|
-
}
|
|
1
|
+
import { modelSnapshotOutWithMetadata } from "mobx-keystone"
|
|
2
|
+
import * as Y from "yjs"
|
|
3
|
+
import { JsonObjectWithUndefined, JsonValueWithUndefined } from "../jsonTypes"
|
|
4
|
+
import { YjsTextModel } from "./YjsTextModel"
|
|
5
|
+
|
|
6
|
+
export type YjsData = Y.Array<YjsData> | Y.Map<YjsData> | Y.Text | JsonValueWithUndefined
|
|
7
|
+
|
|
8
|
+
export function convertYjsDataToJson(yjsData: YjsData): JsonValueWithUndefined {
|
|
9
|
+
if (yjsData instanceof Y.Array) {
|
|
10
|
+
return yjsData.map((v) => convertYjsDataToJson(v))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (yjsData instanceof Y.Map) {
|
|
14
|
+
const obj: JsonObjectWithUndefined = {}
|
|
15
|
+
yjsData.forEach((v, k) => {
|
|
16
|
+
obj[k] = convertYjsDataToJson(v)
|
|
17
|
+
})
|
|
18
|
+
return obj
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (yjsData instanceof Y.Text) {
|
|
22
|
+
const deltas = yjsData.toDelta() as unknown[]
|
|
23
|
+
|
|
24
|
+
return modelSnapshotOutWithMetadata(YjsTextModel, {
|
|
25
|
+
deltaList: deltas.length > 0 ? [{ $frozen: true, data: deltas }] : [],
|
|
26
|
+
}) as unknown as JsonValueWithUndefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// assume it's a primitive
|
|
30
|
+
return yjsData
|
|
31
|
+
}
|
|
@@ -1,92 +1,96 @@
|
|
|
1
|
-
import { Patch } from "mobx-keystone"
|
|
2
|
-
import * as Y from "yjs"
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (change.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
1
|
+
import { Patch } from "mobx-keystone"
|
|
2
|
+
import * as Y from "yjs"
|
|
3
|
+
import {
|
|
4
|
+
JsonArrayWithUndefined,
|
|
5
|
+
JsonObjectWithUndefined,
|
|
6
|
+
JsonValueWithUndefined,
|
|
7
|
+
} from "../jsonTypes"
|
|
8
|
+
import { failure } from "../utils/error"
|
|
9
|
+
|
|
10
|
+
export function convertYjsEventToPatches(event: Y.YEvent<any>): Patch[] {
|
|
11
|
+
const patches: Patch[] = []
|
|
12
|
+
|
|
13
|
+
if (event instanceof Y.YMapEvent) {
|
|
14
|
+
const source = event.target
|
|
15
|
+
|
|
16
|
+
event.changes.keys.forEach((change, key) => {
|
|
17
|
+
const path = [...event.path, key]
|
|
18
|
+
|
|
19
|
+
switch (change.action) {
|
|
20
|
+
case "add":
|
|
21
|
+
patches.push({
|
|
22
|
+
op: "add",
|
|
23
|
+
path,
|
|
24
|
+
value: toPlainValue(source.get(key)),
|
|
25
|
+
})
|
|
26
|
+
break
|
|
27
|
+
|
|
28
|
+
case "update":
|
|
29
|
+
patches.push({
|
|
30
|
+
op: "replace",
|
|
31
|
+
path,
|
|
32
|
+
value: toPlainValue(source.get(key)),
|
|
33
|
+
})
|
|
34
|
+
break
|
|
35
|
+
|
|
36
|
+
case "delete":
|
|
37
|
+
patches.push({
|
|
38
|
+
op: "remove",
|
|
39
|
+
path,
|
|
40
|
+
})
|
|
41
|
+
break
|
|
42
|
+
|
|
43
|
+
default:
|
|
44
|
+
throw failure(`unsupported Yjs map event action: ${change.action}`)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
} else if (event instanceof Y.YArrayEvent) {
|
|
48
|
+
let retain = 0
|
|
49
|
+
event.changes.delta.forEach((change) => {
|
|
50
|
+
if (change.retain) {
|
|
51
|
+
retain += change.retain
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (change.delete) {
|
|
55
|
+
// remove X items at retain position
|
|
56
|
+
const path = [...event.path, retain]
|
|
57
|
+
for (let i = 0; i < change.delete; i++) {
|
|
58
|
+
patches.push({
|
|
59
|
+
op: "remove",
|
|
60
|
+
path,
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (change.insert) {
|
|
66
|
+
const newValues = Array.isArray(change.insert) ? change.insert : [change.insert]
|
|
67
|
+
newValues.forEach((v) => {
|
|
68
|
+
const path = [...event.path, retain]
|
|
69
|
+
patches.push({
|
|
70
|
+
op: "add",
|
|
71
|
+
path,
|
|
72
|
+
value: toPlainValue(v),
|
|
73
|
+
})
|
|
74
|
+
retain++
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
} else if (event instanceof Y.YTextEvent) {
|
|
79
|
+
const path = [...event.path, "deltaList", -1 /* last item */]
|
|
80
|
+
patches.push({
|
|
81
|
+
op: "add",
|
|
82
|
+
path,
|
|
83
|
+
value: { $frozen: true, data: event.delta },
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return patches
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function toPlainValue(v: Y.Map<any> | Y.Array<any> | JsonValueWithUndefined) {
|
|
91
|
+
if (v instanceof Y.Map || v instanceof Y.Array) {
|
|
92
|
+
return v.toJSON() as JsonObjectWithUndefined | JsonArrayWithUndefined
|
|
93
|
+
} else {
|
|
94
|
+
return v
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import * as Y from "yjs"
|
|
2
|
-
import { failure } from "../utils/error"
|
|
3
|
-
import { getOrCreateYjsCollectionAtom } from "../utils/getOrCreateYjsCollectionAtom"
|
|
4
|
-
|
|
5
|
-
export function resolveYjsPath(yjsObject: unknown, path: readonly (string | number)[]): unknown {
|
|
6
|
-
let currentYjsObject: unknown = yjsObject
|
|
7
|
-
|
|
8
|
-
path.forEach((pathPart, i) => {
|
|
9
|
-
if (currentYjsObject instanceof Y.Map) {
|
|
10
|
-
getOrCreateYjsCollectionAtom(currentYjsObject).reportObserved()
|
|
11
|
-
const key = String(pathPart)
|
|
12
|
-
currentYjsObject = currentYjsObject.get(key)
|
|
13
|
-
} else if (currentYjsObject instanceof Y.Array) {
|
|
14
|
-
getOrCreateYjsCollectionAtom(currentYjsObject).reportObserved()
|
|
15
|
-
const key = Number(pathPart)
|
|
16
|
-
currentYjsObject = currentYjsObject.get(key)
|
|
17
|
-
} else {
|
|
18
|
-
throw failure(
|
|
19
|
-
`Y.Map or Y.Array was expected at path ${JSON.stringify(
|
|
20
|
-
path.slice(0, i)
|
|
21
|
-
)} in order to resolve path ${JSON.stringify(path)}, but got ${currentYjsObject} instead`
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
return currentYjsObject
|
|
27
|
-
}
|
|
1
|
+
import * as Y from "yjs"
|
|
2
|
+
import { failure } from "../utils/error"
|
|
3
|
+
import { getOrCreateYjsCollectionAtom } from "../utils/getOrCreateYjsCollectionAtom"
|
|
4
|
+
|
|
5
|
+
export function resolveYjsPath(yjsObject: unknown, path: readonly (string | number)[]): unknown {
|
|
6
|
+
let currentYjsObject: unknown = yjsObject
|
|
7
|
+
|
|
8
|
+
path.forEach((pathPart, i) => {
|
|
9
|
+
if (currentYjsObject instanceof Y.Map) {
|
|
10
|
+
getOrCreateYjsCollectionAtom(currentYjsObject).reportObserved()
|
|
11
|
+
const key = String(pathPart)
|
|
12
|
+
currentYjsObject = currentYjsObject.get(key)
|
|
13
|
+
} else if (currentYjsObject instanceof Y.Array) {
|
|
14
|
+
getOrCreateYjsCollectionAtom(currentYjsObject).reportObserved()
|
|
15
|
+
const key = Number(pathPart)
|
|
16
|
+
currentYjsObject = currentYjsObject.get(key)
|
|
17
|
+
} else {
|
|
18
|
+
throw failure(
|
|
19
|
+
`Y.Map or Y.Array was expected at path ${JSON.stringify(
|
|
20
|
+
path.slice(0, i)
|
|
21
|
+
)} in order to resolve path ${JSON.stringify(path)}, but got ${currentYjsObject} instead`
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return currentYjsObject
|
|
27
|
+
}
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
import { AnyType, createContext } from "mobx-keystone"
|
|
2
|
-
import * as Y from "yjs"
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Context with info on how a mobx-keystone model is bound to a Y.js data structure.
|
|
6
|
-
*/
|
|
7
|
-
export interface YjsBindingContext {
|
|
8
|
-
/**
|
|
9
|
-
* The Y.js document.
|
|
10
|
-
*/
|
|
11
|
-
yjsDoc: Y.Doc
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The bound Y.js data structure.
|
|
15
|
-
*/
|
|
16
|
-
yjsObject: Y.Map<unknown> | Y.Array<unknown> | Y.Text
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* The mobx-keystone model type.
|
|
20
|
-
*/
|
|
21
|
-
mobxKeystoneType: AnyType
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The origin symbol used for transactions.
|
|
25
|
-
*/
|
|
26
|
-
yjsOrigin: symbol
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* The bound mobx-keystone instance.
|
|
30
|
-
*/
|
|
31
|
-
boundObject: unknown
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Whether we are currently applying Y.js changes to the mobx-keystone model.
|
|
35
|
-
*/
|
|
36
|
-
isApplyingYjsChangesToMobxKeystone: boolean
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Context with info on how a mobx-keystone model is bound to a Y.js data structure.
|
|
41
|
-
*/
|
|
42
|
-
export const yjsBindingContext = createContext<YjsBindingContext | undefined>(undefined)
|
|
1
|
+
import { AnyType, createContext } from "mobx-keystone"
|
|
2
|
+
import * as Y from "yjs"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Context with info on how a mobx-keystone model is bound to a Y.js data structure.
|
|
6
|
+
*/
|
|
7
|
+
export interface YjsBindingContext {
|
|
8
|
+
/**
|
|
9
|
+
* The Y.js document.
|
|
10
|
+
*/
|
|
11
|
+
yjsDoc: Y.Doc
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The bound Y.js data structure.
|
|
15
|
+
*/
|
|
16
|
+
yjsObject: Y.Map<unknown> | Y.Array<unknown> | Y.Text
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The mobx-keystone model type.
|
|
20
|
+
*/
|
|
21
|
+
mobxKeystoneType: AnyType
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The origin symbol used for transactions.
|
|
25
|
+
*/
|
|
26
|
+
yjsOrigin: symbol
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The bound mobx-keystone instance.
|
|
30
|
+
*/
|
|
31
|
+
boundObject: unknown
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether we are currently applying Y.js changes to the mobx-keystone model.
|
|
35
|
+
*/
|
|
36
|
+
isApplyingYjsChangesToMobxKeystone: boolean
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Context with info on how a mobx-keystone model is bound to a Y.js data structure.
|
|
41
|
+
*/
|
|
42
|
+
export const yjsBindingContext = createContext<YjsBindingContext | undefined>(undefined)
|
package/src/jsonTypes.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
export type
|
|
2
|
-
export type
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export type JsonPrimitiveWithUndefined = string | number | boolean | null | undefined
|
|
2
|
+
export type JsonValueWithUndefined =
|
|
3
|
+
| JsonPrimitiveWithUndefined
|
|
4
|
+
| JsonObjectWithUndefined
|
|
5
|
+
| JsonArrayWithUndefined
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
7
|
+
export type JsonObjectWithUndefined = { [key: string]: JsonValueWithUndefined }
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
9
|
+
export interface JsonArrayWithUndefined extends Array<JsonValueWithUndefined> {}
|
|
@@ -1,18 +1,27 @@
|
|
|
1
|
-
import { IAtom, createAtom } from "mobx"
|
|
2
|
-
import * as Y from "yjs"
|
|
3
|
-
|
|
4
|
-
const yjsCollectionAtoms = new WeakMap<Y.Map<unknown> | Y.Array<unknown>, IAtom>()
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @internal
|
|
8
|
-
*/
|
|
9
|
-
export const
|
|
10
|
-
yjsCollection: Y.Map<unknown> | Y.Array<unknown>
|
|
11
|
-
): IAtom => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { IAtom, createAtom } from "mobx"
|
|
2
|
+
import * as Y from "yjs"
|
|
3
|
+
|
|
4
|
+
const yjsCollectionAtoms = new WeakMap<Y.Map<unknown> | Y.Array<unknown>, IAtom>()
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export const getYjsCollectionAtom = (
|
|
10
|
+
yjsCollection: Y.Map<unknown> | Y.Array<unknown>
|
|
11
|
+
): IAtom | undefined => {
|
|
12
|
+
return yjsCollectionAtoms.get(yjsCollection)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export const getOrCreateYjsCollectionAtom = (
|
|
19
|
+
yjsCollection: Y.Map<unknown> | Y.Array<unknown>
|
|
20
|
+
): IAtom => {
|
|
21
|
+
let atom = yjsCollectionAtoms.get(yjsCollection)
|
|
22
|
+
if (!atom) {
|
|
23
|
+
atom = createAtom(`yjsCollectionAtom`)
|
|
24
|
+
yjsCollectionAtoms.set(yjsCollection, atom)
|
|
25
|
+
}
|
|
26
|
+
return atom
|
|
27
|
+
}
|