lattyware / elm-json-diff / Json.Patch.Invertible

JSON patches, when structured a specific way, can be inverted to return a patched document to its original form.

Types


type alias Patch =
List Operation

A list of invertible Operations that are performed one after another.


type Operation
    = Add Json.Pointer.Pointer Json.Decode.Value
    | Remove Json.Pointer.Pointer Json.Decode.Value
    | Replace Json.Pointer.Pointer Json.Decode.Value Json.Decode.Value
    | Move Json.Pointer.Pointer Json.Pointer.Pointer

An operation that can be inverted to produce a reverse patch.

This is largely meant to mirror Json.Patch.Operation, but structured with any additional information required to invert the patch.

However, there are some key differences: Test operations are not allowed, as they are used to include the extra information. Copy operations are not allowed, as they are ambiguous (the reverse of a Copy is a Remove, which could then become either an Add or a Copy).

Operations

apply : Patch -> Json.Decode.Value -> Result String Json.Decode.Value

Apply a Patch to a Value.

This is just a convenience function to do patch |> toMinimalPatch |> Json.Patch.apply.

invert : Patch -> Patch

Create a patch that does the inverse of the given one.

patch |> invert |> invert should always result in the same thing as just patch, and value |> (apply patch) |> Result.andThen (apply (patch |> invert)) should produce value (assuming the patch can be applied to the value).

merge : Patch -> Patch

Take a patch and merge any Remove and Add operations that have the same values into single Move options.

The resulting patch should always do the same thing as it did before, but may be smaller.

Compatibility

toPatch : Patch -> Json.Patch.Patch

Create a normal patch from an invertible one.

Note that this patch would still be invertible, you are just losing the type guarantee of that (i.e: you could run fromPatch on it and get a result). To strip the tests and make the patch truly not invertible, see toMinimalPatch instead.

toMinimalPatch : Patch -> Json.Patch.Patch

Create a patch from the invertible one, stripping out the tests that allow inversion.

fromPatch : Json.Patch.Patch -> Result String Patch

Try to create an invertible patch from a normal one. This will only work if the normal patch is structured correctly (with tests before operations to establish the "missing" values).

Diff.invertibleDiff can provide one of these with no chance of failure.