Compressing patches #1976
-
| Is there a way to compress MST patches like in immer? https://medium.com/@dedels/using-immer-to-compress-immer-patches-f382835b6c69 I am handling patches in between snapshots, but noticing that an add followed by a replace operation is not compressed into a singular add, which would be useful so I would only have to handle a single path once. | 
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
| Hi @BrianHung! I just ported that Immer example to MST, and I don't think that is supported. I can't say for certain that it's unachievable, but I don't think it is right now. import { applyPatch, applySnapshot, onPatch, types } from "mobx-state-tree";
const Model = types
  .model({
    a: 1,
    b: types.maybe(types.number)
  })
  .actions((self) => ({
    setA(a: number) {
      self.a = a;
    },
    setB(b: number) {
      self.b = b;
    },
    reset() {
      applySnapshot(self, {});
    }
  }));
const patches: any = [];
const compiledPatches: any = [];
const model = Model.create();
const dispose = onPatch(model, (patch) => patches.push(patch));
model.setB(9);
model.setA(3);
model.setB(99);
model.setA(5);
console.log(patches);
// (4) [Object, Object, Object, Object]
dispose();
model.reset();
onPatch(model, (patch) => compiledPatches.push(patch));
applyPatch(model, patches);
console.log(compiledPatches);
// (4) [Object, Object, Object, Object] | 
Beta Was this translation helpful? Give feedback.
-
| There are two ways of compressing patches. 
 import { applyPatches, enablePatches, Patch, produceWithPatches } from "immer";
import { joinJsonPath, splitJsonPath, type IJsonPatch, isStateTreeNode, getSnapshot } from "mobx-state-tree";
export const getImmerPatch = ({ path, ...patch }: IJsonPatch) => ({ path: splitJsonPath(path), ...patch });
export const getMSTPatch = ({ path, ...patch }: Patch) => ({ path: joinJsonPath(path as string[]), ...patch });
/**
 * Compresses JsonPatches using immer. Requires snapshot of previous state.
 * https://medium.com/@dedels/using-immer-to-compress-immer-patches-f382835b6c69
 * @param prevState
 * @param patches
 * @returns
 */
export function compressImmerPatches(prevState: IEditorState, patches: Patch[]) {
  const snapshot = isStateTreeNode(prevState) ? getSnapshot(prevState) : prevState;
  const [next, compressed, inverse] = produceWithPatches<IEditorState>(snapshot, draft => applyPatches(draft, patches));
  return compressed;
}
const patches = []
onPatch(state, patch => patches.push(patch))
const lastSnapshot = state.toJSON();
onSnapshot(state, snapshot => {
  const compressed compressImmerPatches(lastSnapshot, patches.map(getImmerPatch)).map(getMSTPatch)
  lastSnapshot = snapshot
})
 /**
 * Compresses JsonPatches using a Radix Trie.
 * @param patches
 * @returns
 */
export function compressPatches(patches: Patch[]) {
  const trie = new PatchRadixTrie(patches);
  return  trie.getPatches();
}
const patches = []
onPatch(state, patch => patches.push(patch))
const compressed = compressPatches(patches.map(getImmerPatch)).map(getMSTPatch); | 
Beta Was this translation helpful? Give feedback.
Hi @BrianHung!
I just ported that Immer example to MST, and I don't think that is supported. I can't say for certain that it's unachievable, but I don't think it is right now.