mobx-keystone-yjs 1.5.1 → 1.5.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.
@@ -1,248 +1,247 @@
1
- import { IAtom, computed, createAtom, observe, reaction } from "mobx"
2
- import {
3
- Frozen,
4
- Model,
5
- frozen,
6
- getParentToChildPath,
7
- model,
8
- onSnapshot,
9
- tProp,
10
- types,
11
- } from "mobx-keystone"
12
- import * as Y from "yjs"
13
- import { failure } from "../utils/error"
14
- import { YjsBindingContext, yjsBindingContext } from "./yjsBindingContext"
15
- import { resolveYjsPath } from "./resolveYjsPath"
16
-
17
- // Delta[][], since each single change is a Delta[]
18
- // we use frozen so that we can reuse each delta change
19
- const deltaListType = types.array(types.frozen(types.unchecked<unknown[]>()))
20
-
21
- export const yjsTextModelId = "mobx-keystone-yjs/YjsTextModel"
22
-
23
- /**
24
- * A mobx-keystone model that represents a Yjs.Text object.
25
- */
26
- @model(yjsTextModelId)
27
- export class YjsTextModel extends Model({
28
- deltaList: tProp(deltaListType, () => []),
29
- }) {
30
- /**
31
- * Helper function to create a YjsTextModel instance with a simple text.
32
- */
33
- static withText(text: string): YjsTextModel {
34
- return new DecoratedYjsTextModel({
35
- deltaList: [
36
- frozen([
37
- {
38
- insert: text,
39
- },
40
- ]),
41
- ],
42
- })
43
- }
44
-
45
- /**
46
- * The Y.js path from the bound object to the YjsTextModel instance.
47
- */
48
- @computed
49
- private get _yjsObjectPath() {
50
- const ctx = yjsBindingContext.get(this)
51
- if (ctx?.boundObject == null) {
52
- throw failure(
53
- "the YjsTextModel instance must be part of a bound object before it can be accessed"
54
- )
55
- }
56
-
57
- const path = getParentToChildPath(ctx.boundObject, this)
58
- if (!path) {
59
- throw failure("a path from the bound object to the YjsTextModel instance is not available")
60
- }
61
-
62
- return path
63
- }
64
-
65
- /**
66
- * The Yjs.Text object present at this mobx-keystone node's path.
67
- */
68
- @computed
69
- private get _yjsObjectAtPath(): unknown {
70
- const path = this._yjsObjectPath
71
-
72
- const ctx = yjsBindingContext.get(this)!
73
-
74
- return resolveYjsPath(ctx.yjsObject, path)
75
- }
76
-
77
- /**
78
- * The Yjs.Text object represented by this mobx-keystone node.
79
- */
80
- @computed
81
- get yjsText(): Y.Text {
82
- const yjsObject = this._yjsObjectAtPath
83
-
84
- if (!(yjsObject instanceof Y.Text)) {
85
- throw failure(`Y.Text was expected at path ${JSON.stringify(this._yjsObjectPath)}`)
86
- }
87
-
88
- return yjsObject
89
- }
90
-
91
- /**
92
- * Atom that gets changed when the associated Y.js text changes.
93
- */
94
- yjsTextChangedAtom = createAtom("yjsTextChangedAtom")
95
-
96
- /**
97
- * The text value of the Yjs.Text object.
98
- * Shortcut for `yjsText.toString()`, but computed.
99
- */
100
- @computed
101
- get text(): string {
102
- this.yjsTextChangedAtom.reportObserved()
103
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
104
- return this.yjsText.toString()
105
- }
106
-
107
- protected onInit() {
108
- const shouldReplicateToYjs = (ctx: YjsBindingContext | undefined): ctx is YjsBindingContext => {
109
- return !!ctx && !!ctx.boundObject && !ctx.isApplyingYjsChangesToMobxKeystone
110
- }
111
-
112
- let reapplyDeltasToYjsText = false
113
- const newDeltas: Frozen<unknown[]>[] = []
114
-
115
- let disposeObserveDeltaList: (() => void) | undefined
116
-
117
- const disposeReactionToDeltaListRefChange = reaction(
118
- () => this.$.deltaList,
119
- (deltaList) => {
120
- disposeObserveDeltaList?.()
121
- disposeObserveDeltaList = undefined
122
-
123
- disposeObserveDeltaList = observe(deltaList, (change) => {
124
- if (reapplyDeltasToYjsText) {
125
- // already gonna replace them all
126
- return
127
- }
128
- if (!shouldReplicateToYjs(yjsBindingContext.get(this))) {
129
- // yjs text is already up to date with these changes
130
- return
131
- }
132
-
133
- if (
134
- change.type === "splice" &&
135
- change.removedCount === 0 &&
136
- change.addedCount > 0 &&
137
- change.index === this.deltaList.length
138
- ) {
139
- // optimization, just adding new ones to the end
140
- newDeltas.push(...change.added)
141
- } else {
142
- // any other change, we need to reapply all deltas
143
- reapplyDeltasToYjsText = true
144
- }
145
- })
146
- },
147
- { fireImmediately: true }
148
- )
149
-
150
- const disposeOnSnapshot = onSnapshot(this, () => {
151
- try {
152
- if (reapplyDeltasToYjsText) {
153
- const ctx = yjsBindingContext.get(this)
154
-
155
- if (shouldReplicateToYjs(ctx)) {
156
- const { yjsText } = this
157
-
158
- ctx.yjsDoc.transact(() => {
159
- // didn't find a better way than this to reapply all deltas
160
- // without having to re-create the Y.Text object
161
- if (yjsText.length > 0) {
162
- yjsText.delete(0, yjsText.length)
163
- }
164
-
165
- this.deltaList.forEach((frozenDeltas) => {
166
- yjsText.applyDelta(frozenDeltas.data)
167
- })
168
- }, ctx.yjsOrigin)
169
- }
170
- } else if (newDeltas.length > 0) {
171
- const ctx = yjsBindingContext.get(this)
172
-
173
- if (shouldReplicateToYjs(ctx)) {
174
- const { yjsText } = this
175
-
176
- ctx.yjsDoc.transact(() => {
177
- newDeltas.forEach((frozenDeltas) => {
178
- yjsText.applyDelta(frozenDeltas.data)
179
- })
180
- }, ctx.yjsOrigin)
181
- }
182
- }
183
- } finally {
184
- reapplyDeltasToYjsText = false
185
- newDeltas.length = 0
186
- }
187
- })
188
-
189
- const diposeYjsTextChangedAtom = hookYjsTextChangedAtom(
190
- () => this.yjsText,
191
- this.yjsTextChangedAtom
192
- )
193
-
194
- return () => {
195
- disposeOnSnapshot()
196
- disposeReactionToDeltaListRefChange()
197
- disposeObserveDeltaList?.()
198
- disposeObserveDeltaList = undefined
199
-
200
- diposeYjsTextChangedAtom()
201
- }
202
- }
203
- }
204
-
205
- // we use this trick just to avoid a babel bug that causes classes used inside classes not to be overriden
206
- // by the decorator
207
- const DecoratedYjsTextModel = YjsTextModel
208
-
209
- function hookYjsTextChangedAtom(getYjsText: () => Y.Text, textChangedAtom: IAtom) {
210
- let disposeObserveYjsText: (() => void) | undefined
211
-
212
- const observeFn = () => {
213
- textChangedAtom.reportChanged()
214
- }
215
-
216
- const disposeReactionToYTextChange = reaction(
217
- () => {
218
- try {
219
- return getYjsText()
220
- } catch {
221
- return undefined
222
- }
223
- },
224
- (yjsText) => {
225
- disposeObserveYjsText?.()
226
- disposeObserveYjsText = undefined
227
-
228
- if (yjsText) {
229
- yjsText.observe(observeFn)
230
-
231
- disposeObserveYjsText = () => {
232
- yjsText.unobserve(observeFn)
233
- }
234
- }
235
-
236
- textChangedAtom.reportChanged()
237
- },
238
- {
239
- fireImmediately: true,
240
- }
241
- )
242
-
243
- return () => {
244
- disposeReactionToYTextChange()
245
- disposeObserveYjsText?.()
246
- disposeObserveYjsText = undefined
247
- }
248
- }
1
+ import { IAtom, computed, createAtom, observe, reaction } from "mobx"
2
+ import {
3
+ Frozen,
4
+ Model,
5
+ frozen,
6
+ getParentToChildPath,
7
+ model,
8
+ onSnapshot,
9
+ tProp,
10
+ types,
11
+ } from "mobx-keystone"
12
+ import * as Y from "yjs"
13
+ import { failure } from "../utils/error"
14
+ import { YjsBindingContext, yjsBindingContext } from "./yjsBindingContext"
15
+ import { resolveYjsPath } from "./resolveYjsPath"
16
+
17
+ // Delta[][], since each single change is a Delta[]
18
+ // we use frozen so that we can reuse each delta change
19
+ const deltaListType = types.array(types.frozen(types.unchecked<unknown[]>()))
20
+
21
+ export const yjsTextModelId = "mobx-keystone-yjs/YjsTextModel"
22
+
23
+ /**
24
+ * A mobx-keystone model that represents a Yjs.Text object.
25
+ */
26
+ @model(yjsTextModelId)
27
+ export class YjsTextModel extends Model({
28
+ deltaList: tProp(deltaListType, () => []),
29
+ }) {
30
+ /**
31
+ * Helper function to create a YjsTextModel instance with a simple text.
32
+ */
33
+ static withText(text: string): YjsTextModel {
34
+ return new DecoratedYjsTextModel({
35
+ deltaList: [
36
+ frozen([
37
+ {
38
+ insert: text,
39
+ },
40
+ ]),
41
+ ],
42
+ })
43
+ }
44
+
45
+ /**
46
+ * The Y.js path from the bound object to the YjsTextModel instance.
47
+ */
48
+ @computed
49
+ private get _yjsObjectPath() {
50
+ const ctx = yjsBindingContext.get(this)
51
+ if (ctx?.boundObject == null) {
52
+ throw failure(
53
+ "the YjsTextModel instance must be part of a bound object before it can be accessed"
54
+ )
55
+ }
56
+
57
+ const path = getParentToChildPath(ctx.boundObject, this)
58
+ if (!path) {
59
+ throw failure("a path from the bound object to the YjsTextModel instance is not available")
60
+ }
61
+
62
+ return path
63
+ }
64
+
65
+ /**
66
+ * The Yjs.Text object present at this mobx-keystone node's path.
67
+ */
68
+ @computed
69
+ private get _yjsObjectAtPath(): unknown {
70
+ const path = this._yjsObjectPath
71
+
72
+ const ctx = yjsBindingContext.get(this)!
73
+
74
+ return resolveYjsPath(ctx.yjsObject, path)
75
+ }
76
+
77
+ /**
78
+ * The Yjs.Text object represented by this mobx-keystone node.
79
+ */
80
+ @computed
81
+ get yjsText(): Y.Text {
82
+ const yjsObject = this._yjsObjectAtPath
83
+
84
+ if (!(yjsObject instanceof Y.Text)) {
85
+ throw failure(`Y.Text was expected at path ${JSON.stringify(this._yjsObjectPath)}`)
86
+ }
87
+
88
+ return yjsObject
89
+ }
90
+
91
+ /**
92
+ * Atom that gets changed when the associated Y.js text changes.
93
+ */
94
+ yjsTextChangedAtom = createAtom("yjsTextChangedAtom")
95
+
96
+ /**
97
+ * The text value of the Yjs.Text object.
98
+ * Shortcut for `yjsText.toString()`, but computed.
99
+ */
100
+ @computed
101
+ get text(): string {
102
+ this.yjsTextChangedAtom.reportObserved()
103
+ return this.yjsText.toString()
104
+ }
105
+
106
+ protected onInit() {
107
+ const shouldReplicateToYjs = (ctx: YjsBindingContext | undefined): ctx is YjsBindingContext => {
108
+ return !!ctx && !!ctx.boundObject && !ctx.isApplyingYjsChangesToMobxKeystone
109
+ }
110
+
111
+ let reapplyDeltasToYjsText = false
112
+ const newDeltas: Frozen<unknown[]>[] = []
113
+
114
+ let disposeObserveDeltaList: (() => void) | undefined
115
+
116
+ const disposeReactionToDeltaListRefChange = reaction(
117
+ () => this.$.deltaList,
118
+ (deltaList) => {
119
+ disposeObserveDeltaList?.()
120
+ disposeObserveDeltaList = undefined
121
+
122
+ disposeObserveDeltaList = observe(deltaList, (change) => {
123
+ if (reapplyDeltasToYjsText) {
124
+ // already gonna replace them all
125
+ return
126
+ }
127
+ if (!shouldReplicateToYjs(yjsBindingContext.get(this))) {
128
+ // yjs text is already up to date with these changes
129
+ return
130
+ }
131
+
132
+ if (
133
+ change.type === "splice" &&
134
+ change.removedCount === 0 &&
135
+ change.addedCount > 0 &&
136
+ change.index === this.deltaList.length
137
+ ) {
138
+ // optimization, just adding new ones to the end
139
+ newDeltas.push(...change.added)
140
+ } else {
141
+ // any other change, we need to reapply all deltas
142
+ reapplyDeltasToYjsText = true
143
+ }
144
+ })
145
+ },
146
+ { fireImmediately: true }
147
+ )
148
+
149
+ const disposeOnSnapshot = onSnapshot(this, () => {
150
+ try {
151
+ if (reapplyDeltasToYjsText) {
152
+ const ctx = yjsBindingContext.get(this)
153
+
154
+ if (shouldReplicateToYjs(ctx)) {
155
+ const { yjsText } = this
156
+
157
+ ctx.yjsDoc.transact(() => {
158
+ // didn't find a better way than this to reapply all deltas
159
+ // without having to re-create the Y.Text object
160
+ if (yjsText.length > 0) {
161
+ yjsText.delete(0, yjsText.length)
162
+ }
163
+
164
+ this.deltaList.forEach((frozenDeltas) => {
165
+ yjsText.applyDelta(frozenDeltas.data)
166
+ })
167
+ }, ctx.yjsOrigin)
168
+ }
169
+ } else if (newDeltas.length > 0) {
170
+ const ctx = yjsBindingContext.get(this)
171
+
172
+ if (shouldReplicateToYjs(ctx)) {
173
+ const { yjsText } = this
174
+
175
+ ctx.yjsDoc.transact(() => {
176
+ newDeltas.forEach((frozenDeltas) => {
177
+ yjsText.applyDelta(frozenDeltas.data)
178
+ })
179
+ }, ctx.yjsOrigin)
180
+ }
181
+ }
182
+ } finally {
183
+ reapplyDeltasToYjsText = false
184
+ newDeltas.length = 0
185
+ }
186
+ })
187
+
188
+ const diposeYjsTextChangedAtom = hookYjsTextChangedAtom(
189
+ () => this.yjsText,
190
+ this.yjsTextChangedAtom
191
+ )
192
+
193
+ return () => {
194
+ disposeOnSnapshot()
195
+ disposeReactionToDeltaListRefChange()
196
+ disposeObserveDeltaList?.()
197
+ disposeObserveDeltaList = undefined
198
+
199
+ diposeYjsTextChangedAtom()
200
+ }
201
+ }
202
+ }
203
+
204
+ // we use this trick just to avoid a babel bug that causes classes used inside classes not to be overriden
205
+ // by the decorator
206
+ const DecoratedYjsTextModel = YjsTextModel
207
+
208
+ function hookYjsTextChangedAtom(getYjsText: () => Y.Text, textChangedAtom: IAtom) {
209
+ let disposeObserveYjsText: (() => void) | undefined
210
+
211
+ const observeFn = () => {
212
+ textChangedAtom.reportChanged()
213
+ }
214
+
215
+ const disposeReactionToYTextChange = reaction(
216
+ () => {
217
+ try {
218
+ return getYjsText()
219
+ } catch {
220
+ return undefined
221
+ }
222
+ },
223
+ (yjsText) => {
224
+ disposeObserveYjsText?.()
225
+ disposeObserveYjsText = undefined
226
+
227
+ if (yjsText) {
228
+ yjsText.observe(observeFn)
229
+
230
+ disposeObserveYjsText = () => {
231
+ yjsText.unobserve(observeFn)
232
+ }
233
+ }
234
+
235
+ textChangedAtom.reportChanged()
236
+ },
237
+ {
238
+ fireImmediately: true,
239
+ }
240
+ )
241
+
242
+ return () => {
243
+ disposeReactionToYTextChange()
244
+ disposeObserveYjsText?.()
245
+ disposeObserveYjsText = undefined
246
+ }
247
+ }
@@ -2,7 +2,7 @@ import { Patch } from "mobx-keystone"
2
2
  import * as Y from "yjs"
3
3
  import { failure } from "../utils/error"
4
4
  import { convertJsonToYjsData } from "./convertJsonToYjsData"
5
- import { JsonValueWithUndefined } from "../jsonTypes"
5
+ import { PlainValue } from "../plainTypes"
6
6
 
7
7
  export function applyMobxKeystonePatchToYjsObject(patch: Patch, yjs: unknown): void {
8
8
  if (patch.path.length > 1) {
@@ -42,7 +42,7 @@ export function applyMobxKeystonePatchToYjsObject(patch: Patch, yjs: unknown): v
42
42
  switch (patch.op) {
43
43
  case "add":
44
44
  case "replace": {
45
- yjs.set(key, convertJsonToYjsData(patch.value as JsonValueWithUndefined))
45
+ yjs.set(key, convertJsonToYjsData(patch.value as PlainValue))
46
46
  break
47
47
  }
48
48
  case "remove": {
@@ -65,16 +65,16 @@ export function applyMobxKeystonePatchToYjsObject(patch: Patch, yjs: unknown): v
65
65
  yjs.delete(newLength, toDelete)
66
66
  } else if (yjs.length < patch.value) {
67
67
  const toInsert = patch.value - yjs.length
68
- yjs.insert(yjs.length, Array(toInsert).fill(undefined))
68
+ yjs.insert(yjs.length, Array.from({ length: toInsert }).fill(undefined))
69
69
  }
70
70
  } else {
71
71
  yjs.delete(Number(key))
72
- yjs.insert(Number(key), [convertJsonToYjsData(patch.value as JsonValueWithUndefined)])
72
+ yjs.insert(Number(key), [convertJsonToYjsData(patch.value as PlainValue)])
73
73
  }
74
74
  break
75
75
  }
76
76
  case "add": {
77
- yjs.insert(Number(key), [convertJsonToYjsData(patch.value as JsonValueWithUndefined)])
77
+ yjs.insert(Number(key), [convertJsonToYjsData(patch.value as PlainValue)])
78
78
  break
79
79
  }
80
80
  case "remove": {
@@ -2,43 +2,38 @@ import * as Y from "yjs"
2
2
  import { YjsTextModel, yjsTextModelId } from "./YjsTextModel"
3
3
  import { SnapshotOutOf } from "mobx-keystone"
4
4
  import { YjsData } from "./convertYjsDataToJson"
5
- import {
6
- JsonArrayWithUndefined,
7
- JsonObjectWithUndefined,
8
- JsonPrimitiveWithUndefined,
9
- JsonValueWithUndefined,
10
- } from "../jsonTypes"
5
+ import { PlainArray, PlainObject, PlainPrimitive, PlainValue } from "../plainTypes"
11
6
 
12
- function isJsonPrimitiveWithUndefined(v: JsonValueWithUndefined): v is JsonPrimitiveWithUndefined {
7
+ function isPlainPrimitive(v: PlainValue): v is PlainPrimitive {
13
8
  const t = typeof v
14
9
  return t === "string" || t === "number" || t === "boolean" || v === null || v === undefined
15
10
  }
16
11
 
17
- function isJsonArrayWithUndefined(v: JsonValueWithUndefined): v is JsonArrayWithUndefined {
12
+ function isPlainArray(v: PlainValue): v is PlainArray {
18
13
  return Array.isArray(v)
19
14
  }
20
15
 
21
- function isJsonObjectWithUndefined(v: JsonValueWithUndefined): v is JsonObjectWithUndefined {
22
- return !isJsonArrayWithUndefined(v) && typeof v === "object"
16
+ function isPlainObject(v: PlainValue): v is PlainObject {
17
+ return !isPlainArray(v) && typeof v === "object" && v !== null
23
18
  }
24
19
 
25
20
  /**
26
- * Converts a JSON value to a Y.js data structure.
21
+ * Converts a plain value to a Y.js data structure.
27
22
  * Objects are converted to Y.Maps, arrays to Y.Arrays, primitives are untouched.
28
23
  * Frozen values are a special case and they are kept as immutable plain values.
29
24
  */
30
- export function convertJsonToYjsData(v: JsonValueWithUndefined | undefined): YjsData {
31
- if (v === undefined || isJsonPrimitiveWithUndefined(v)) {
25
+ export function convertJsonToYjsData(v: PlainValue): YjsData {
26
+ if (isPlainPrimitive(v)) {
32
27
  return v
33
28
  }
34
29
 
35
- if (isJsonArrayWithUndefined(v)) {
30
+ if (isPlainArray(v)) {
36
31
  const arr = new Y.Array()
37
32
  applyJsonArrayToYArray(arr, v)
38
33
  return arr as YjsData
39
34
  }
40
35
 
41
- if (isJsonObjectWithUndefined(v)) {
36
+ if (isPlainObject(v)) {
42
37
  if (v.$frozen === true) {
43
38
  // frozen value, save as immutable object
44
39
  return v
@@ -64,14 +59,14 @@ export function convertJsonToYjsData(v: JsonValueWithUndefined | undefined): Yjs
64
59
  /**
65
60
  * Applies a JSON array to a Y.Array, using the convertJsonToYjsData to convert the values.
66
61
  */
67
- export function applyJsonArrayToYArray(dest: Y.Array<unknown>, source: JsonArrayWithUndefined) {
62
+ export function applyJsonArrayToYArray(dest: Y.Array<unknown>, source: PlainArray) {
68
63
  dest.push(source.map(convertJsonToYjsData))
69
64
  }
70
65
 
71
66
  /**
72
67
  * Applies a JSON object to a Y.Map, using the convertJsonToYjsData to convert the values.
73
68
  */
74
- export function applyJsonObjectToYMap(dest: Y.Map<unknown>, source: JsonObjectWithUndefined) {
69
+ export function applyJsonObjectToYMap(dest: Y.Map<unknown>, source: PlainObject) {
75
70
  Object.entries(source).forEach(([k, v]) => {
76
71
  dest.set(k, convertJsonToYjsData(v))
77
72
  })
@@ -1,17 +1,17 @@
1
1
  import { modelSnapshotOutWithMetadata } from "mobx-keystone"
2
2
  import * as Y from "yjs"
3
- import { JsonObjectWithUndefined, JsonValueWithUndefined } from "../jsonTypes"
3
+ import { PlainObject, PlainValue } from "../plainTypes"
4
4
  import { YjsTextModel } from "./YjsTextModel"
5
5
 
6
- export type YjsData = Y.Array<YjsData> | Y.Map<YjsData> | Y.Text | JsonValueWithUndefined
6
+ export type YjsData = Y.Array<YjsData> | Y.Map<YjsData> | Y.Text | PlainValue
7
7
 
8
- export function convertYjsDataToJson(yjsData: YjsData): JsonValueWithUndefined {
8
+ export function convertYjsDataToJson(yjsData: YjsData): PlainValue {
9
9
  if (yjsData instanceof Y.Array) {
10
10
  return yjsData.map((v) => convertYjsDataToJson(v))
11
11
  }
12
12
 
13
13
  if (yjsData instanceof Y.Map) {
14
- const obj: JsonObjectWithUndefined = {}
14
+ const obj: PlainObject = {}
15
15
  yjsData.forEach((v, k) => {
16
16
  obj[k] = convertYjsDataToJson(v)
17
17
  })
@@ -23,7 +23,7 @@ export function convertYjsDataToJson(yjsData: YjsData): JsonValueWithUndefined {
23
23
 
24
24
  return modelSnapshotOutWithMetadata(YjsTextModel, {
25
25
  deltaList: deltas.length > 0 ? [{ $frozen: true, data: deltas }] : [],
26
- }) as unknown as JsonValueWithUndefined
26
+ }) as unknown as PlainValue
27
27
  }
28
28
 
29
29
  // assume it's a primitive
@@ -1,10 +1,6 @@
1
1
  import { Patch } from "mobx-keystone"
2
2
  import * as Y from "yjs"
3
- import {
4
- JsonArrayWithUndefined,
5
- JsonObjectWithUndefined,
6
- JsonValueWithUndefined,
7
- } from "../jsonTypes"
3
+ import { PlainArray, PlainObject, PlainValue } from "../plainTypes"
8
4
  import { failure } from "../utils/error"
9
5
 
10
6
  export function convertYjsEventToPatches(event: Y.YEvent<any>): Patch[] {
@@ -87,9 +83,9 @@ export function convertYjsEventToPatches(event: Y.YEvent<any>): Patch[] {
87
83
  return patches
88
84
  }
89
85
 
90
- function toPlainValue(v: Y.Map<any> | Y.Array<any> | JsonValueWithUndefined) {
86
+ function toPlainValue(v: Y.Map<any> | Y.Array<any> | PlainValue) {
91
87
  if (v instanceof Y.Map || v instanceof Y.Array) {
92
- return v.toJSON() as JsonObjectWithUndefined | JsonArrayWithUndefined
88
+ return v.toJSON() as PlainObject | PlainArray
93
89
  } else {
94
90
  return v
95
91
  }