Guide / JavaScript /

Patches

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] }

Delete

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 }

Replace

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

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] }

Swap

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] }

Multi

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"] }

Unpatch

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 }

encode & decode

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 →