Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compare() creates PATCHES that cannot be applied immediately afterwards #280

Open
NicBright opened this issue Aug 16, 2021 · 3 comments
Open

Comments

@NicBright
Copy link

NicBright commented Aug 16, 2021

Thanks @Starcounter-Jack for your quick response in #279 and for the thoughts you've given this! I think you're right, from the point of view of JSON specification. That is, undefined is not a valid value and therefore properties with value undefined need to be treated as "inexistent".

Nevertheless, I think there's still a problem there in the way how fast-json-patch creates patches. (From the point of view of the problem I've described in #279) The root cause actually is, that fast-json-patch creates patches it is not able to apply directly afterwards on the source document.

This should work basically, but it doesn't:

const { compare, applyPatch } = require('fast-json-patch');

const from = { schaden: undefined };
const to = { schaden: { id: 'my-id' } };

const patches = compare(from, to);
console.log(patches); // logs [ { op: 'replace', path: '/schaden', value: { id: 'my-id' } } ]

applyPatch(from, patches, true); // throws 'OPERATION_PATH_UNRESOLVABLE'

So maybe the correct fix would be to alter the way the patch is created in the first place? For example, if the patch would be an 'add' operation it would work as expected

@nadilas
Copy link

nadilas commented Mar 2, 2024

Just ran into the same issue. @NicBright have you looked into the issue, how we could adapt the code to account for the proper add operation?

@NicBright
Copy link
Author

NicBright commented Mar 6, 2024

@nadilas We're working around the issue like this:

        try {
            applyOperation(document, operation, validateOperation);
        } catch (e) {
            // Try to recover:
            if (e.name === 'OPERATION_PATH_UNRESOLVABLE') {
                if (operation.op === 'replace') {
                    // Can happen e.g. when states are like this:
                    // from.schaden = undefined;
                    // to.schaden.id = 'some-id';
                    operation.op = 'add'; // try it once more with operation "add" instead
                    applyOperation(document, operation, validateOperation);
                } else if (operation.op === 'remove') {
                    // Can happen e.g. when states are like this:
                    // from.entity.begruendung = null;
                    // to.entity.begruendung = undefined;
                    // we don't do anything in this case because "to" is already in a good state!
                }
            } else {
                // otherwise we just rethrow ...
                throw e;
            }
        }

@nadilas
Copy link

nadilas commented Mar 23, 2024

This worked out great, thanks @NicBright for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants