UNPKG

mobx-keystone-yjs

Version:

Yjs bindings for mobx-keystone

93 lines (81 loc) 2.29 kB
import { Patch } from "mobx-keystone" import * as Y from "yjs" import { PlainArray, PlainObject, PlainValue } from "../plainTypes" import { failure } from "../utils/error" export function convertYjsEventToPatches(event: Y.YEvent<any>): Patch[] { const patches: Patch[] = [] if (event instanceof Y.YMapEvent) { const source = event.target event.changes.keys.forEach((change, key) => { const path = [...event.path, key] switch (change.action) { case "add": patches.push({ op: "add", path, value: toPlainValue(source.get(key)), }) break case "update": patches.push({ op: "replace", path, value: toPlainValue(source.get(key)), }) break case "delete": patches.push({ op: "remove", path, }) break default: throw failure(`unsupported Yjs map event action: ${change.action}`) } }) } else if (event instanceof Y.YArrayEvent) { let retain = 0 event.changes.delta.forEach((change) => { if (change.retain) { retain += change.retain } if (change.delete) { // remove X items at retain position const path = [...event.path, retain] for (let i = 0; i < change.delete; i++) { patches.push({ op: "remove", path, }) } } if (change.insert) { const newValues = Array.isArray(change.insert) ? change.insert : [change.insert] newValues.forEach((v) => { const path = [...event.path, retain] patches.push({ op: "add", path, value: toPlainValue(v), }) retain++ }) } }) } else if (event instanceof Y.YTextEvent) { const path = [...event.path, "deltaList", -1 /* last item */] patches.push({ op: "add", path, value: { $frozen: true, data: event.delta }, }) } return patches } function toPlainValue(v: Y.Map<any> | Y.Array<any> | PlainValue) { if (v instanceof Y.Map || v instanceof Y.Array) { return v.toJSON() as PlainObject | PlainArray } else { return v } }