import { JSORMBase , ModelRecord , ModelAttributeChangeSet } from "../model" ; import { IncludeDirective , IncludeScopeHash } from "./include-directive" ; import { IncludeScope } from "../scope" ; import { JsonapiResourceIdentifier } from "../jsonapi-spec" ; class DirtyChecker < T extends JSORMBase > { model : T ; constructor ( model ) { this . model = model ; } checkRelation ( relationName , relatedModel ) { let dirty = false ; if ( relatedModel . isPersisted ) { const identifiers = ( < any > this . model ) . _originalRelationships [ relationName ] || [ ] ; const found = identifiers . find ( ri => { return ( JSON . stringify ( ri ) === JSON . stringify ( relatedModel . resourceIdentifier ) ) ; } ) ; if ( ! found ) { dirty = true ; } } return dirty ; } check ( relationships = { } ) { const includeDirective = new IncludeDirective ( relationships ) ; const includeHash = includeDirective . toScopeObject ( ) ; return ( this . _hasDirtyAttributes ( ) || this . _hasDirtyRelationships ( includeHash ) || this . model . isMarkedForDestruction || this . model . isMarkedForDisassociation || this . _isUnpersisted ( ) ) ; } dirtyAttributes ( ) { const dirty = { } ; for ( const key of Object . keys ( this . model . attributes ) ) { const prior = ( < any > this . model ) . _originalAttributes [ key ] ; const current = this . model . attributes [ key ] ; if ( ! this . model . isPersisted ) { dirty [ key ] = [ null , current ] ; } else if ( prior !== current ) { dirty [ key ] = [ prior , current ] ; } } return dirty ; } private _isUnpersisted ( ) { return ( ! this . model . isPersisted && JSON . stringify ( this . model . attributes ) !== JSON . stringify ( { } ) ) ; } private _hasDirtyAttributes ( ) { const originalAttrs = ( < any > this . model ) . _originalAttributes ; const currentAttrs = this . model . attributes ; return JSON . stringify ( originalAttrs ) !== JSON . stringify ( currentAttrs ) ; } private _hasDirtyRelationships ( includeHash ) { let dirty = false ; this . _eachRelatedObject ( includeHash , ( relationName , relatedObject , nested ) => { if ( relatedObject . isDirty ( nested ) ) { dirty = true ; } if ( this . checkRelation ( relationName , relatedObject ) ) { dirty = true ; } } ) ; return dirty ; } private _eachRelatedObject ( includeHash , callback ) { Object . keys ( includeHash ) . forEach ( key => { const nested = includeHash [ key ] ; let relatedObjects = ( < any > this . model ) [ key ] ; if ( ! Array . isArray ( relatedObjects ) ) { relatedObjects = [ relatedObjects ] ; } relatedObjects . forEach ( relatedObject => { if ( relatedObject ) { callback ( key , relatedObject , nested ) ; } } ) ; } ) ; } } export default DirtyChecker ;