Skip to content

Commit

Permalink
Rename IDiff->Diff, ITryDiff->VoidableDiff; add wrapVoidableDiff helper
Browse files Browse the repository at this point in the history
  • Loading branch information
chbrown committed Jun 25, 2018
1 parent b0e895e commit 725f501
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 35 deletions.
26 changes: 5 additions & 21 deletions diff.ts
Expand Up @@ -42,9 +42,8 @@ export function isDestructive({op}: Operation): boolean {
return op === 'remove' || op === 'replace' || op === 'copy' || op === 'move'
}

export interface IDiff {
(input: any, output: any, ptr: Pointer): Operation[]
}
export type Diff = (input: any, output: any, ptr: Pointer) => Operation[]
export type VoidableDiff = (input: any, output: any, ptr: Pointer) => Operation[] | void

/**
subtract(a, b) returns the keys in `a` that are not in `b`.
Expand Down Expand Up @@ -143,12 +142,7 @@ if input (source) is empty, they'll all be in the top row, just a bunch of
additions. If the output is empty, everything will be in the left column, as a
bunch of deletions.
*/
export function diffArrays<T>(
input: T[],
output: T[],
ptr: Pointer,
diff: IDiff = diffAny,
): Operation[] {
export function diffArrays<T>(input: T[], output: T[], ptr: Pointer, diff: Diff = diffAny): Operation[] {
// set up cost matrix (very simple initialization: just a map)
const memo: {[index: string]: DynamicAlternative} = {
'0,0': {operations: [], cost: 0},
Expand Down Expand Up @@ -261,12 +255,7 @@ export function diffArrays<T>(
return padded_operations
}

export function diffObjects(
input: any,
output: any,
ptr: Pointer,
diff: IDiff = diffAny,
): Operation[] {
export function diffObjects(input: any, output: any, ptr: Pointer, diff: Diff = diffAny): Operation[] {
// if a key is in input but not output -> remove it
const operations: Operation[] = []
subtract(input, output).forEach(key => {
Expand All @@ -290,12 +279,7 @@ export function diffValues(input: any, output: any, ptr: Pointer): Operation[] {
return []
}

export function diffAny(
input: any,
output: any,
ptr: Pointer,
diff: IDiff = diffAny,
): Operation[] {
export function diffAny(input: any, output: any, ptr: Pointer, diff: Diff = diffAny): Operation[] {
const input_type = objectType(input)
const output_type = objectType(output)
if (input_type == 'array' && output_type == 'array') {
Expand Down
25 changes: 11 additions & 14 deletions index.ts
Expand Up @@ -2,7 +2,7 @@ import {InvalidOperationError} from './errors'
import {Pointer} from './pointer'

import * as operationFunctions from './patch'
import {Operation, TestOperation, isDestructive, diffAny} from './diff'
import {Operation, TestOperation, isDestructive, Diff, VoidableDiff, diffAny} from './diff'

export {Operation, TestOperation}
export type Patch = Operation[]
Expand Down Expand Up @@ -35,8 +35,13 @@ export function applyPatch(object, patch) {
})
}

export interface ITryDiff {
(input: any, output: any, ptr: Pointer): Operation[] | void
function wrapVoidableDiff(diff: VoidableDiff): Diff {
function wrappedDiff(input: any, output: any, ptr: Pointer) {
const custom_patch = diff(input, output, ptr)
// ensure an array is always returned
return Array.isArray(custom_patch) ? custom_patch : diffAny(input, output, ptr, wrappedDiff)
}
return wrappedDiff
}

/**
Expand All @@ -47,23 +52,15 @@ 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`
`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: any,
output: any,
diff?: ITryDiff,
): Operation[] {
export function createPatch(input: any, output: any, diff?: VoidableDiff): Operation[] {
const ptr = new Pointer()
// a new Pointer gets a default path of [''] if not specified
function safeDiff(input, output, ptr) {
// ensure an array is always returned
return diff(input, output, ptr) || diffAny(input, output, ptr, safeDiff)
}
return diff ? safeDiff(input, output, ptr) : diffAny(input, output, ptr)
return (diff ? wrapVoidableDiff(diff) : diffAny)(input, output, ptr)
}

function createTest(input: any, path: string): TestOperation {
Expand Down

0 comments on commit 725f501

Please sign in to comment.