ShareDB Integration

I’m interested in integrating ProseMirror collab with ShareDB. This question has been asked by others before but didn’t gain much traction, so I’ll ask again with a little more detail.

At a glance, a ShareDB OT & a ProseMirror Step appear quite similar. I’m wondering if it’s possible to wrap a Step within a custom OT type? This would be similar to how rich-text does for a QuillDelta.

I tried an implementation myself but got stumped implementing transform (op1, op2, side) as it doesn’t seem like we can apply a Step to another Step. I thought about using a Transform instead, though it doesn’t seem possible to Transform a Transform either.

I’m not an expert in this space, so I’m perhaps misunderstanding the difference between the ShareDB & ProseMirror collab model. I’ve read marijn’s collab post probably forty times & believe I understand why OTs weren’t used to begin with.

Is a ShareDB integration feasible? Or is this a dead end?


1 Like

I know nothing of ShareDB and whether combining it with ProseMirror is going to work, but something like might be what you’re looking for here (though step mapping does not take a parameter like side, and as such might not cover what you want).

1 Like

@marijn, thank you so much for your reply.

Does .map actually transform the Step itself? I thought it just transformed the character position mappings? Or am i thinking about this wrong?

The quill example defined transform like so:

const a = new Delta().insert('a');
const b = new Delta().insert('b').retain(5).insert('c');

a.transform(b, true);  // new Delta().retain(1).insert('b').retain(5).insert('c');
a.transform(b, false); // new Delta().insert('b').retain(6).insert('c');

Maybe i should be considering wrapping a Step[] inside a ShareDB OT?

@marijn You’re right. I misread what transform is supposed to do.

I ended up wrapping an array of Step’s. I think i have it working? Are there any red flags that anyone sees?

Update: Removed broken code to not lead anyone else astray

Indeed, with map lacking a side, it doesn’t seem to work. This is my latest attempt. After this post, i’ll stop live coding. But would love to talk with anyone more about this approach.

function mapToSide (source: Mappable, side: 'left' | 'right'): Mappable {
  const assoc = side === 'left' ? -1 : 1

  return {
    map (pos: number): number {
      return, assoc)

    mapResult (pos: number): MapResult {
      return source.mapResult(pos, assoc)

function transform (a: unknown[], b: unknown[], side: 'left' | 'right'): unknown[] {
  const mapping = mapToSide(getMapping(b), side)

  return => {
    const result = deserializeStep(step).map(mapping)
    if (result == null) throw new Error('Could not transform ProseMirror Step')
    return result.toJSON()