cujojs / jiff

JSON Patch and diff based on rfc6902
Other
627 stars 41 forks source link

Proposal: invertible remove, replace, and copy #15

Open briancavalier opened 10 years ago

briancavalier commented 10 years ago

Given the discussion in #9, and our decision to (ab)use test for now, I figured we could use this issue to focus in on other alternatives that allow patch inversion. We could potentially propose additions/changes to RFC6902.

briancavalier commented 10 years ago

Proposal 1: Use test

As described in #9, and implemented in #14. However, I don't think this helps with copy.

briancavalier commented 10 years ago

Proposal 2: Add inverse property

As suggested by @unscriptable, we could add an inverse property to remove, replace, and copy operations that captures, verbatim the patch operation that should be used to invert the operation in question.

This is nice and clean, and seems to have the nice property that the producer of the patch operation can provide all the necessary information for inverting, and the inversion algorithm itself can be more generic.

briancavalier commented 10 years ago

Proposal 3: Augment remove and replace, invent uncopy

We could add new properties to the problematic operations to help with inversion, and invent a new uncopy operation that is the inverse of copy.

  1. remove - add value property which contains the value being removed. Implementations could choose to treat this value like a test when removing. To invert, generate an add with the same value. When inverting add, always generate a remove with value.
  2. replace - add oldValue (or a better name, please!) which contains the value being replace. Implementations could choose to treat this value like a test when removing. To invert, generate a replace that swaps value and oldValue.
  3. uncopy - a new operation that is the inversion of copy. It is looks like a copy and when applied, behaves like remove. The key is the operation name can trigger different behavior during inversion.

    { op: 'copy', path: '/b', from: '/a' } <--> { op: 'uncopy', path: '/b', from: '/a' }
briancavalier commented 10 years ago

Just to clarify: the problem with copy is not that it can't be inverted--it can, to remove. The problem is that remove has 2 inverses: add and copy. So, inverse(inverse(copy)) can't be determined.