microdiff icon indicating copy to clipboard operation
microdiff copied to clipboard

Recreation from diff

Open FluentCoding opened this issue 3 years ago • 8 comments

Hey!

I'm currently considering to use microdiff for my project, however I also have to be able to recreate an object from the diff and the source object (basically so that im able to send smaller-sized updates to a client state via a websocket connection), but it seems like microdiff is not offering any method for this. I will implement this in my project but I would like to know if this is in the ToDo.

FluentCoding avatar Nov 08 '21 11:11 FluentCoding

Yeah, I plan to add patching soon. I can’t give you an exact ETA, but it will probably be a week or two. I will give you an update when I release it.

AsyncBanana avatar Nov 08 '21 11:11 AsyncBanana

Alright, thanks! I'm down to help you at this, you can hit me up on discord (FluentCoding#3314) if you want to discuss the API/implementation.

FluentCoding avatar Nov 08 '21 11:11 FluentCoding

this might be the same as what you're thinking for patching, but is it possible to lump together CHANGE events with similar paths? So

{
  path: [ 'states', 0, 'jsonlist', 61, 'offsetP', 'x' ],
  type: 'CHANGE',
  value: 569.73
},
{
  path: [ 'states', 0, 'jsonlist', 61, 'offsetP', 'y' ],
  type: 'CHANGE',
  value: 266.862
},

would become

{
  path: [ 'states', 0, 'jsonlist', 61, 'offsetP' ],
  type: 'CHANGE',
  value: { x: 569.73, y: 266.862 }
},

gorkermann avatar Nov 21 '21 01:11 gorkermann

I think you could do this but at the cost of a bit of performance as you would have to look up the equal path parents and then combine them.

FluentCoding avatar Nov 24 '21 13:11 FluentCoding

Oh, also, related to this issue, here is the PR that I posted about 11 days ago: https://github.com/AsyncBanana/microdiff/pull/13

FluentCoding avatar Nov 24 '21 13:11 FluentCoding

If you have lodash in your project, here is how I'm currently experimenting with patch functionality:

function patch (target: any, diff: any[]): any {
  target = cloneDeep(target);

  for (let i = 0; i < diff.length; i++) {
    const {
      type,
      path,
      value,
    } = diff[i];

    switch (type) {
      case 'CREATE': {
        set(target, path, value);
        break;
      }
      case 'CHANGE': {
        set(target, path, value);
        break;
      }
      case 'REMOVE': {
        // Note this does not actually remove the entry
        set(target, path, undefined);
        break;
      }
      default: {
        throw new Error(`unknown diff entry type: ${type}`);
      }
    }
  }

  return target;
}

Hopefully this helps someone waiting for the patch functionality. It would be less trivial to implement without lodash, but doable. I'm not sure how REMOVE would work - right now I'm just setting it to undefined, but that isn't the same as removal since the ownEnumerableProperty still exists.

brainthinks avatar Jan 12 '22 01:01 brainthinks

Would lodash.unset work here for the REMOVE?

steveruizok avatar Jul 30 '22 08:07 steveruizok

Micropatch is where FluentCoding's implementation ended up. Currently, you can use it directly from GitHub, and I am working on publishing it to NPM.

AsyncBanana avatar Jul 30 '22 13:07 AsyncBanana