@@ -9,6 +9,8 @@ import _extend from './util/extend';
9
9
import { camelize } from './util/string' ;
10
10
import WritePayload from './util/write-payload' ;
11
11
import IncludeDirective from './util/include-directive' ;
12
+ import DirtyChecker from './util/dirty-check' ;
13
+ import relationshipIdentifiersFor from './util/relationship-identifiers' ;
12
14
import Request from './request' ;
13
15
import * as _cloneDeep from './util/clonedeep' ;
14
16
let cloneDeep : any = ( < any > _cloneDeep ) . default || _cloneDeep ;
@@ -26,13 +28,18 @@ export default class Model {
26
28
static parentClass : typeof Model ;
27
29
28
30
id : string ;
31
+ temp_id : string ;
29
32
_attributes : Object = { } ;
33
+ _originalAttributes : Object = { } ;
34
+ _originalRelationships : Object = { } ;
30
35
relationships : Object = { } ;
31
36
__meta__ : Object | void = null ;
32
37
_persisted : boolean = false ;
38
+ _markedForDestruction : boolean = false ;
33
39
klass : typeof Model ;
34
40
35
41
static attributeList = [ ] ;
42
+ static relationList = [ ] ;
36
43
private static _scope : Scope ;
37
44
38
45
static extend ( obj : any ) : any {
@@ -138,12 +145,31 @@ export default class Model {
138
145
139
146
constructor ( attributes ?: Object ) {
140
147
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 ) ;
141
163
}
142
164
143
165
isType ( jsonapiType : string ) {
144
166
return this . klass . jsonapiType === jsonapiType ;
145
167
}
146
168
169
+ get resourceIdentifier ( ) : Object {
170
+ return { type : this . klass . jsonapiType , id : this . id } ;
171
+ }
172
+
147
173
get attributes ( ) : Object {
148
174
return this . _attributes ;
149
175
}
@@ -160,16 +186,37 @@ export default class Model {
160
186
isPersisted ( val ? : boolean ) : boolean {
161
187
if ( val != undefined ) {
162
188
this . _persisted = val ;
189
+ this . _originalAttributes = cloneDeep ( this . attributes ) ;
190
+ this . _originalRelationships = this . relationshipResourceIdentifiers ( Object . keys ( this . relationships ) ) ;
163
191
return val ;
164
192
} else {
165
193
return this . _persisted ;
166
194
}
167
195
}
168
196
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
+
169
206
fromJsonapi ( resource : japiResource , payload : japiDoc ) : any {
170
207
return deserializeInstance ( this , resource , payload ) ;
171
208
}
172
209
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
+
173
220
destroy ( ) : Promise < any > {
174
221
let url = this . klass . url ( this . id ) ;
175
222
let verb = 'delete' ;
@@ -182,35 +229,35 @@ export default class Model {
182
229
} ) ;
183
230
}
184
231
185
- save ( ) : Promise < any > {
232
+ save ( options : Object = { } ) : Promise < any > {
186
233
let url = this . klass . url ( ) ;
187
234
let verb = 'post' ;
188
235
let request = new Request ( ) ;
189
- let payload = new WritePayload ( this ) ;
236
+ let payload = new WritePayload ( this , options [ 'with' ] ) ;
190
237
let jwt = this . klass . getJWT ( ) ;
191
238
192
239
if ( this . isPersisted ( ) ) {
193
240
url = this . klass . url ( this . id ) ;
194
241
verb = 'put' ;
195
242
}
196
243
197
- let requestPromise = request [ verb ] ( url , payload . asJSON ( ) , { jwt } ) ;
244
+ let json = payload . asJSON ( ) ;
245
+ let requestPromise = request [ verb ] ( url , json , { jwt } ) ;
198
246
return this . _writeRequest ( requestPromise , ( ) => {
199
247
this . isPersisted ( true ) ;
248
+ payload . postProcess ( ) ;
200
249
} ) ;
201
250
}
202
251
203
- private
204
-
205
- _writeRequest ( requestPromise : Promise < any > , callback : Function ) : Promise < any > {
252
+ private _writeRequest ( requestPromise : Promise < any > , callback : Function ) : Promise < any > {
206
253
return new Promise ( ( resolve , reject ) => {
207
254
return requestPromise . then ( ( response ) => {
208
255
this . _handleResponse ( response , resolve , reject , callback ) ;
209
256
} ) ;
210
257
} ) ;
211
258
}
212
259
213
- _handleResponse ( response : any , resolve : Function , reject : Function , callback : Function ) : void {
260
+ private _handleResponse ( response : any , resolve : Function , reject : Function , callback : Function ) : void {
214
261
if ( response . status == 422 ) {
215
262
resolve ( false ) ;
216
263
} else if ( response . status >= 500 ) {
0 commit comments