@@ -9,6 +9,8 @@ import _extend from './util/extend';
99import { camelize } from './util/string' ;
1010import WritePayload from './util/write-payload' ;
1111import IncludeDirective from './util/include-directive' ;
12+ import DirtyChecker from './util/dirty-check' ;
13+ import relationshipIdentifiersFor from './util/relationship-identifiers' ;
1214import Request from './request' ;
1315import * as _cloneDeep from './util/clonedeep' ;
1416let cloneDeep : any = ( < any > _cloneDeep ) . default || _cloneDeep ;
@@ -26,13 +28,18 @@ export default class Model {
2628 static parentClass : typeof Model ;
2729
2830 id : string ;
31+ temp_id : string ;
2932 _attributes : Object = { } ;
33+ _originalAttributes : Object = { } ;
34+ _originalRelationships : Object = { } ;
3035 relationships : Object = { } ;
3136 __meta__ : Object | void = null ;
3237 _persisted : boolean = false ;
38+ _markedForDestruction : boolean = false ;
3339 klass : typeof Model ;
3440
3541 static attributeList = [ ] ;
42+ static relationList = [ ] ;
3643 private static _scope : Scope ;
3744
3845 static extend ( obj : any ) : any {
@@ -138,12 +145,31 @@ export default class Model {
138145
139146 constructor ( attributes ?: Object ) {
140147 this . attributes = attributes ;
148+ this . _originalAttributes = cloneDeep ( this . attributes ) ;
149+ this . _originalRelationships = this . relationshipResourceIdentifiers ( Object . keys ( this . relationships ) ) ;
150+ }
151+
152+ // Todo:
153+ // * needs to recurse the directive
154+ // * remove the corresponding code from isPersisted and handle here (likely
155+ // only an issue with test setup)
156+ // * Make all calls go through resetRelationTracking();
157+ resetRelationTracking ( includeDirective : Object ) {
158+ this . _originalRelationships = this . relationshipResourceIdentifiers ( Object . keys ( includeDirective ) ) ;
159+ }
160+
161+ relationshipResourceIdentifiers ( relationNames : Array < string > ) {
162+ return relationshipIdentifiersFor ( this , relationNames ) ;
141163 }
142164
143165 isType ( jsonapiType : string ) {
144166 return this . klass . jsonapiType === jsonapiType ;
145167 }
146168
169+ get resourceIdentifier ( ) : Object {
170+ return { type : this . klass . jsonapiType , id : this . id } ;
171+ }
172+
147173 get attributes ( ) : Object {
148174 return this . _attributes ;
149175 }
@@ -160,16 +186,37 @@ export default class Model {
160186 isPersisted ( val ? : boolean ) : boolean {
161187 if ( val != undefined ) {
162188 this . _persisted = val ;
189+ this . _originalAttributes = cloneDeep ( this . attributes ) ;
190+ this . _originalRelationships = this . relationshipResourceIdentifiers ( Object . keys ( this . relationships ) ) ;
163191 return val ;
164192 } else {
165193 return this . _persisted ;
166194 }
167195 }
168196
197+ isMarkedForDestruction ( val ? : boolean ) : boolean {
198+ if ( val != undefined ) {
199+ this . _markedForDestruction = val ;
200+ return val ;
201+ } else {
202+ return this . _markedForDestruction ;
203+ }
204+ }
205+
169206 fromJsonapi ( resource : japiResource , payload : japiDoc ) : any {
170207 return deserializeInstance ( this , resource , payload ) ;
171208 }
172209
210+ isDirty ( relationships ?: Object | Array < any > | string ) : boolean {
211+ let dc = new DirtyChecker ( this ) ;
212+ return dc . check ( relationships ) ;
213+ }
214+
215+ hasDirtyRelation ( relationName : string , relatedModel : Model ) : boolean {
216+ let dc = new DirtyChecker ( this ) ;
217+ return dc . checkRelation ( relationName , relatedModel ) ;
218+ }
219+
173220 destroy ( ) : Promise < any > {
174221 let url = this . klass . url ( this . id ) ;
175222 let verb = 'delete' ;
@@ -182,35 +229,35 @@ export default class Model {
182229 } ) ;
183230 }
184231
185- save ( ) : Promise < any > {
232+ save ( options : Object = { } ) : Promise < any > {
186233 let url = this . klass . url ( ) ;
187234 let verb = 'post' ;
188235 let request = new Request ( ) ;
189- let payload = new WritePayload ( this ) ;
236+ let payload = new WritePayload ( this , options [ 'with' ] ) ;
190237 let jwt = this . klass . getJWT ( ) ;
191238
192239 if ( this . isPersisted ( ) ) {
193240 url = this . klass . url ( this . id ) ;
194241 verb = 'put' ;
195242 }
196243
197- let requestPromise = request [ verb ] ( url , payload . asJSON ( ) , { jwt } ) ;
244+ let json = payload . asJSON ( ) ;
245+ let requestPromise = request [ verb ] ( url , json , { jwt } ) ;
198246 return this . _writeRequest ( requestPromise , ( ) => {
199247 this . isPersisted ( true ) ;
248+ payload . postProcess ( ) ;
200249 } ) ;
201250 }
202251
203- private
204-
205- _writeRequest ( requestPromise : Promise < any > , callback : Function ) : Promise < any > {
252+ private _writeRequest ( requestPromise : Promise < any > , callback : Function ) : Promise < any > {
206253 return new Promise ( ( resolve , reject ) => {
207254 return requestPromise . then ( ( response ) => {
208255 this . _handleResponse ( response , resolve , reject , callback ) ;
209256 } ) ;
210257 } ) ;
211258 }
212259
213- _handleResponse ( response : any , resolve : Function , reject : Function , callback : Function ) : void {
260+ private _handleResponse ( response : any , resolve : Function , reject : Function , callback : Function ) : void {
214261 if ( response . status == 422 ) {
215262 resolve ( false ) ;
216263 } else if ( response . status >= 500 ) {
0 commit comments