Rebuilding code file in backend does not match frontend

Hi all,

I’m noticing that sometimes my backend is not able to rebuild the code the same way as the frontend. I think this is because codemirror uses dispatch to implement updates on the frontend, but in the backend you are stuck manipulating the document directly.

How I’m doing it in the backend:

let doc = Text.of(startingText.split("\n"));

    for (const update of codeMirrorUpdates) {
      try {
        const updateObj = JSON.parse(update);
        // console.log("updateObj", updateObj, "startingText", startingText);
        let changes = ChangeSet.fromJSON(updateObj.changes);

        console.log("changes", changes);

        doc = doc.apply(changes);
      } catch (error) {
        console.log("one codemirror update broke");
      }
    }

    return doc.toString();

How I’m doing it in the frontend:

this.view.dispatch(receiveUpdates(this.view.state, updates));

Note that I am using the @codemirror/collab in the frontend. I would assume that wouldn’t make a difference? Not sure though.

It would mean a lot if I could get this solved, thanks so much!

I’m not sure how you collected codeMirrorUpdates, but if those are an actual sequence of changes that were applied in that order before, then running over them like that should work. But if some of those ended up being mapped over other changes before being applied, because they happened concurrently, then obviously they won’t ‘fit’ when applied in their original form.

The updates were applied in that exact order before. And since I have a frontend and a backend, I can verify that the codeMirrorUpdates is correct because the frontend shows the correct code, but the backend runs into errors saying that the changes are out of range when trying to rebuild the file

The difference in approach between the frontend and backend might indeed be causing the inconsistency.

In the frontend, you’re using dispatch to apply updates to the CodeMirror instance. This is the recommended way to make changes to the editor’s state because it ensures that the changes are applied correctly and consistently with respect to the editor’s internal state.

In the backend, however, you’re directly manipulating the document without using dispatch. This could indeed lead to inconsistencies because you’re bypassing the mechanism that CodeMirror provides for applying updates safely.

To address this issue, you should try to mimic the frontend behavior in the backend as closely as possible. Since you’re using the @codemirror/collab package in the frontend, you should also use it in the backend to ensure consistency in how updates are applied.

Here’s a general approach you can take:

Install @codemirror/collab in your backend if you haven’t already: npm install @codemirror/collab

Use the same mechanism for applying updates in both the frontend and the backend. Instead of directly manipulating the document, use the provided functions from @codemirror/collab to apply updates:
import { Text, ChangeSet } from “@codemirror/state”;
import { receiveUpdates, TextUpdate } from “@codemirror/collab”;

let doc = Text.of(startingText.split(“\n”));

for (const update of codeMirrorUpdates) {
try {
const updateObj = JSON.parse(update);
const changes = ChangeSet.fromJSON(updateObj.changes);

const textUpdate = new TextUpdate(updateObj.clientID, changes);
doc = receiveUpdates(doc, [textUpdate]);

} catch (error) {
console.log(“One CodeMirror update broke:”, error);
}
}

return doc.toString();
By using receiveUpdates, you’re ensuring that updates are applied correctly according to the collaborative editing protocol, which should help to synchronize the backend’s document state with the frontend’s. If my advice didn’t work for you, you can consult software development experts https://tech-stack.com/services/backend-development-services