A patch describes mutations to be made in our state using plain objects. Is like using Object.assign but in a more advanced way.
A quick example.
import { applyPatch } from 'dop' const target = { a: 1 } const patch = { a: 2 } applyPatch(target, patch) console.log(target) // { a: 2 } Extending
const target = { a: 1 } const patch = { b: 'World' } // target { a: 1, b: 'World' } Mutating and extending
const target = { a: 1 } const patch = { a: 'Hello', b: 'World' } // target { a: 'Hello', b: 'World' } Deep mutation
const target = { a: 1, b: { c: false } } const patch = { b: { c: true } } // target { a: 1, b: { c: true } } const target = {} const patch = { b: { c: 3 } } // target { b: { c: 3 } } If the patch is an array this will always be replaced
const target = { a: [1, 2, 3] } const patch = { a: [4] } // target { a: [4] } const target = { a: { b:true } } const patch = { a: [1,2,3] } // target { a: [1,2,3] } But we can mutate arrays as we do with objects
const target = { a: [1,2,3] } const patch = { a: { 3: 4 } } // target { a: [1,2,3,4] } const target = { a: [1,2,3,4,5] } const patch = { a: { length: 1 } } // target { a: [1] } We must use a special type in order to delete properties
import { applyPatch, TYPE } from 'dop' const target = { a: 1, b: 2 } const patch = { a: TYPE.Delete() } // target { b: 2 } You can replace a whole object using the special type Replace
import { applyPatch, TYPE } from 'dop' const target = { obj: { a: 1, b: 2 } } const patch = { obj: TYPE.Replace({ c: 3 }) } // target { obj: { c: 3 } } If we would't use Replace the result would be
const target = { obj: { a: 1, b: 2 } } const patch = { obj: { c: 3 } } // target { obj: { a: 1, b: 2, c: 3 } } Splice let us add or remove items directly into arrays. It follow the same API of the JavaScript splice method.
import { applyPatch, TYPE } from 'dop' const target = { array: [1,2,3]} const patch = { array: TYPE.Splice(1,1,'Hello','World') } // target { array: [1,'Hello','World',3] } We can swap items in arrays.
import { applyPatch, TYPE } from 'dop' const target = { array: [1,2,3]} const patch = { array: TYPE.Swap(0,2) } // target { array: [3,2,1] } Useful when we want to apply multiple operations to the same target.
import { applyPatch, TYPE } from 'dop' const target = { array: "String"} const patch = { array: TYPE.Multi( [1,2,3], // [1,2,3] TYPE.Splice(0,0,"Hello"), // ["Hello",1,2,3] TYPE.Splice(4,0,"World"), // ["Hello",1,2,3,"World"] TYPE.Swap(0,4), // ["World",1,2,3,"Hello"] TYPE.Swap(1,3), // ["World",3,2,1,"Hello"] )} // target { array: ["World",3,2,1,"Hello"] } We can revert any patch using the unpatch value that we obtain with applyPatch.
import { applyPatch, TYPE } from 'dop' const target = { a:1 } const patch = { a:TYPE.Delete(), b:2 } const { unpatch } = applyPatch(target, patch) console.log(target) // { b:2 } applyPatch(target, unpatch) console.log(target) // { a:1 } One of the main feature of dop is that patches can be encoded and decoded to be transfered via HTTP, WebSockets or any other way.
import { encode, decode, TYPE } from 'dop' const patch = { a:TYPE.Delete(), b:2 } const encoded = JSON.stringify(encode(patch)) // "{"a":{"$d":0},"b":2}" decode(JSON.parse(encoded)) // { a:TYPE.Delete(), b:2 } Stores →