Getting delta on Ymap & Yarray

Hi community,

I’m trying to compute delta between two Ysnapshots with the help of prosemiror demo & binding I was to be able to generate a first draft like this one:

const getDelta = (sharedType, prevSnapshot = Y.emptySnapshot) => {
  if (sharedType.doc) {
    const nextSnapshot = Y.snapshot(sharedType.doc)

    if (Y.equalSnapshots(prevSnapshot, nextSnapshot)) {
      return undefined
    }

    const computeTextChanges = (text: Y.Text) => text.toDelta(
      nextSnapshot,
      prevSnapshot,
      (type, { client }) => ({ type, client })
    )

    const computeNodeChanges = (node: Y.Map<any>) => {
      if (node.has('type')) {
        console.info('Type', node.get('type').constructor.name)
        const children = node.get('children')
        if (children && children.constructor === Y.Array) {
          const computedChildren = computeArrayChanges(children)
          if (Object.keys(computedChildren).length > 0) {
            return {
              children: computedChildren,
              // How to have attribute diff?
            }
          }
        }
      }
      if (node.has('text')) {
        const text = node.get('text')
        if (text && text.constructor === Y.Text) {
          const delta = computeTextChanges(text)
          if (delta.length > 0) {
            return delta
          }
        }
      }
      return {}
    }

    const computeArrayChanges = (array: Y.Array<any>) => {
      const sparseTree = {}
      Y.typeListToArraySnapshot(array, new Y.Snapshot(prevSnapshot.ds, nextSnapshot.sv)).forEach((elm, index) => {
        const tmp = computeNodeChanges(elm)
        if (Object.keys(tmp).length > 0) {
          sparseTree[index] = tmp
        }
      })
      return sparseTree
    }

    return computeArrayChanges(sharedType)
  }
  return undefined
}

I’m wondering how I could know that one element is new or removed in an array? I’ve seen some Y.isVisible from Snapshot (btw not exported) but not sure how I can get to know elements got removed or inserted.

Then it is nearly the same question on a Ymap how I get to know attribute got added/deleted/replaced?

Thanks in advance for your help :wink:

Also quite interested in this - @Hideman85 did you ever figure it out? Basically looking for an efficient method of identifying the SharedTypes that have been added/deleted/updated between two snapshots (where the types are deeply nested).

If you are working with Y.snapshot you have everything you need.

  • Get prevSnapshot & nextSnapshot to compare the differences
  • Is an Item deleted? Y.isDeleted(prevSnapshot.ds, item.id)
  • Compare the known clock in both snapshot clock = prevSnapshot.sv.get(node.id.client) || 0
  • Iterate over type with node = item._start & node = node.right (everything is a linked list)

At the end I did not built a generic algo for computing deltas between two snapshots because it can become really crazy.
In my use case I have a really basic tree [{ children: [{ children: [{ text: 'Hello' }] }] with a few other attributes, so I computed a simple sparse delta tree following the same structure.
If you need to handle structural change, it can be more tricky.

Anyway, the piece of code in my original post can already give you some hint to build your own delta tree.