import Vault from "../../core/Vault" ; import { createVaultFacade } from "../../facades/vault" ; import { History } from "../../types" ; const PRIMATIVES = [ "string" , "number" , "boolean" , "undefined" ] ; export interface CommonRecentCommandResult { a : number ; b : number ; } param historyA param historyB returns function calculateCommonRecentCommand ( historyA , historyB ) { const getCommandType = fullCommand => ( fullCommand && fullCommand . length >= 3 ? fullCommand . substr ( 0 , 3 ) : "" ) ; const getPaddingID = command => command . split ( " " ) [ 1 ] ; for ( let a = historyA . length - 1 ; a >= 9 ; a -= 1 ) { if ( getCommandType ( historyA [ a ] ) === "pad" ) { const paddingA = getPaddingID ( historyA [ a ] ) ; for ( let b = historyB . length - 1 ; b >= 0 ; b -= 1 ) { if ( getCommandType ( historyB [ b ] ) === "pad" && getPaddingID ( historyB [ b ] ) === paddingA ) { return { a , b } ; } } } } return null ; } export interface HistoryDifferences { original : History ; secondary : History ; common : History ; } returns function calculateHistoryDifferences ( historyA , historyB ) { const workingA = [ ... historyA ] ; const workingB = [ ... historyB ] ; const commonIndexes = calculateCommonRecentCommand ( workingA , workingB ) ; if ( commonIndexes === null ) { return null ; } return { original : workingA . splice ( commonIndexes . a + 1 , workingA . length ) , secondary : workingB . splice ( commonIndexes . b + 1 , workingB . length ) , common : workingA } ; } param arr returns function dedupe < T > ( arr ) { return arr . filter ( function ( item , pos ) { return arr . indexOf ( item ) === pos ; } ) ; } param object1 param object2 returns private function different ( object1 , object2 ) { if ( Array . isArray ( object1 ) && Array . isArray ( object2 ) ) { let differs = object1 . some ( function ( item1 ) { return ! object2 . some ( function ( item2 ) { return different ( item1 , item2 ) === false ; } ) ; } ) ; if ( ! differs ) { return object2 . some ( function ( item1 ) { return ! object1 . some ( function ( item2 ) { return different ( item1 , item2 ) === false ; } ) ; } ) ; } } else if ( typeof object1 === "object" && typeof object2 === "object" ) { if ( object1 === null && object2 === null ) { return false ; } let allKeys = dedupe ( [ ... Object . keys ( object1 ) , ... Object . keys ( object2 ) ] ) , isMissingAKey = allKeys . some ( function ( key ) { return ! ( object1 . hasOwnProperty ( key ) && object2 . hasOwnProperty ( key ) ) ; } ) ; if ( ! isMissingAKey ) { return allKeys . some ( function ( key ) { return different ( object1 [ key ] , object2 [ key ] ) ; } ) ; } } else if ( PRIMATIVES . indexOf ( typeof object1 ) === PRIMATIVES . indexOf ( typeof object2 ) ) { return object1 !== object2 ; } return true ; } /**
 * Vault comparison class
 */ export default class VaultComparator { static calculateHistoryDifferences ( historyA , historyB ) { return calculateHistoryDifferences ( historyA , historyB ) ; } _vaultA : Vault ; _vaultB : Vault ; param originalVault param secondaryVault constructor ( originalVault , secondaryVault ) { this . _vaultA = originalVault ; this . _vaultB = secondaryVault ; } returns memberof calculateDifferences ( ) { return VaultComparator . calculateHistoryDifferences ( this . _vaultA . format . history , this . _vaultB . format . history ) ; } returns memberof vaultsDiffer ( ) { const objA = createVaultFacade ( this . _vaultA ) ; const objB = createVaultFacade ( this . _vaultB ) ; delete objA . id ; delete objB . id ; delete objA . _tag ; delete objB . _tag ; return different ( objA , objB ) ; } }