import { Pointer } from './pointer' ; import { apply } from './patch' ; import { Operation , TestOperation , isDestructive , Diff , VoidableDiff , diffAny } from './diff' ; export { Operation , TestOperation } ; export type Patch = Operation [ ] ; returns export function applyPatch ( object , patch ) { return patch . map ( operation => apply ( object , operation ) ) ; } function wrapVoidableDiff ( diff ) { function wrappedDiff ( input , output , ptr ) { const custom_patch = diff ( input , output , ptr ) ; return Array . isArray ( custom_patch ) ? custom_patch : diffAny ( input , output , ptr , wrappedDiff ) ; } return wrappedDiff ; } /**
Produce a 'application/json-patch+json'-type patch to get from one object to
another.

This does not alter `input` or `output` unless they have a property getter with
side-effects (which is not a good idea anyway).

`diff` is called on each pair of comparable non-primitive nodes in the
`input`/`output` object trees, producing nested patches. Return `undefined`
to fall back to default behaviour.

Returns list of operations to perform on `input` to produce `output`.
*/ export function createPatch ( input , output , diff ? ) { const ptr = new Pointer ( ) ; return ( diff ? wrapVoidableDiff ( diff ) : diffAny ) ( input , output , ptr ) ; } /**
Create a test operation based on `input`'s current evaluation of the JSON
Pointer `path`; if such a pointer cannot be resolved, returns undefined.
*/ function createTest ( input , path ) { const endpoint = Pointer . fromJSON ( path ) . evaluate ( input ) ; if ( endpoint !== undefined ) { return { op : 'test' , path , value : endpoint . value } ; } } /**
Produce an 'application/json-patch+json'-type list of tests, to verify that
existing values in an object are identical to the those captured at some
checkpoint (whenever this function is called).

This does not alter `input` or `output` unless they have a property getter with
side-effects (which is not a good idea anyway).

Returns list of test operations.
*/ export function createTests ( input , patch ) { const tests = new Array < TestOperation > ( ) ; patch . filter ( isDestructive ) . forEach ( operation => { const pathTest = createTest ( input , operation . path ) ; if ( pathTest ) tests . push ( pathTest ) ; if ( 'from' in operation ) { const fromTest = createTest ( input , operation . from ) ; if ( fromTest ) tests . push ( fromTest ) ; } } ) ; return tests ; }