mattphillips / deep-object-diff

Deep diffs two objects, including nested structures of arrays and objects, and returns the difference. ❄️
https://www.npmjs.com/package/deep-object-diff
MIT License
1.05k stars 89 forks source link

is there any apply method ? #71

Open maxired opened 2 years ago

maxired commented 2 years ago

Hi,

I was not able to find any apply method which would allow us to take a diff, and apply it to an object. Is there one somewhere? Maybe in another repo?

As a user, I want to be able to compute a diff, send it to a remote host, and apply it (reverse it?), to compute the whole object. Or should I rather use libraries based on jsonpatch ?

jorgebodega commented 2 years ago

That will be really great to have!

mattphillips commented 2 years ago

Hi @maxired this library doesn't currently support anything like this. Are you able to give a concrete example of what you would like to happen?

I've never used jsonpatch but I would imagine to compute an original object from a diff you would need some sort of metadata to describe the changes (which isn't something currently supported by deep-object-diff).

jorgebodega commented 2 years ago

Maybe I can give you an use case.

I have a functionality where the users must fulfill a multistep form, stored like JSON object in database, and must support versioning, because users can fulfill that as many times as they want.

Will be great if I could store just the diffs, and apply them to the schema.

Right now I'm busy and couldn't provide an example with code, I would do it later

maxired commented 2 years ago

Hi @maxired this library doesn't currently support anything like this. Are you able to give a concrete example of what you would like to happen?

Hi @mattphillips, thanks for your answer. I am already using your library in my current project. We use it server-side to do some diff of our redux store, and then update our DB based on diff computed by deep-object-diff. To make it clear, we don't store the diff in that case, but use it to know request to do.

But we have this other user use case where we are reevaluating our options. Since we are already using deep-object-diff, we decided to check if deep-object-diff would fit our needs. We have a real-time server, dealing with multiple web clients. The clients and the server are sharing replicated shared states.

The goal of the server is to merge the different changes and propagate them to other clients. It also has its own business, so it's not only a matter of sharing data sent by other clients.

Anyway, at each interval, the server computes a new state and needs to propagate it to the other clients. To reduce bandwidth and client CPU, we would like to be able to compute a diff between the new computed states and the previous state from a client, and then only send that diff. Upon reception, the client would apply that diff, to locally compute its new state. That's where we imagine using a diff and apply solution.

I've never used jsonpatch but I would imagine to compute an original object from a diff you would need some sort of metadata to describe the changes (which isn't something currently supported by deep-object-diff).

TBH, I don't know much about JSON Patch either, but I am not sure it really creates more data than detailedDiff is doing.

here is the output corresponding to the diff of detailedDiff

[
    {
        "op": "replace",
        "path": "/buzz",
        "value": "fizz"
    },
    {
        "op": "remove",
        "path": "/foo/bar/e"
    },
    {
        "op": "add",
        "path": "/foo/bar/c/2",
        "value": "z"
    },
    {
        "op": "remove",
        "path": "/foo/bar/a/1"
    },
    {
        "op": "add",
        "path": "/foo/bar/d",
        "value": "Hello, world!"
    }
]

we can see it uses an array. Not sure if that's important to keep the order of operation.

PS: we are not dealing with conflict between our clients, and so don't need CRDT or similar solutions

lmaccherone commented 1 year ago

Here is applyDiff module that works with the diff() method not the detailedDiff() method.

It passes all of the deep-object-diff tests as you can see here.

If you want, I can publish it as it's own npm package and/or create a pull request to upgrade deep-object-diff to include this code and test.

lmaccherone commented 1 year ago

I ended up publishing this as its own npm package: https://www.npmjs.com/package/@transformation-dev/deep-object-diff-apply

gregfenton commented 1 year ago

@lmaccherone Looks like your master branch on GH hasn't yet merged in the deep-object-diff-apply package?

gregfenton commented 1 year ago

Use case is pretty straight-forward: Using a document-store database (think MongoDB or Firestore). A "document" is simply a JS object (or JSON object). When an update is being done to the document, I want to calculate the diff and store the diff in some type of history or audit collection (table). I can then use those deltas over time to identify who changed what in that object. The document in the main collection is the "current state" of the data, and the diffs in the audit table are the changes to the data over time (in reverse order).

A storage-level "version control" for business objects!! :)