@ember-data/store 4.1.0 → 4.2.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/-private/system/core-store.ts +135 -495
- package/addon/-private/system/ds-model-store.ts +12 -63
- package/addon/-private/system/model/internal-model.ts +90 -342
- package/addon/-private/system/model/states.js +2 -14
- package/addon/-private/system/record-array-manager.js +3 -30
- package/addon/-private/system/references/belongs-to.ts +11 -26
- package/addon/-private/system/references/has-many.ts +14 -33
- package/addon/-private/system/references/record.ts +9 -23
- package/addon/-private/system/references/reference.ts +3 -25
- package/addon/-private/system/snapshot.ts +22 -48
- package/addon/-private/system/store/finders.js +2 -58
- package/addon/-private/system/store/record-data-store-wrapper.ts +17 -24
- package/package.json +8 -8
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
import { getOwner, setOwner } from '@ember/application';
|
|
2
1
|
import { A, default as EmberArray } from '@ember/array';
|
|
3
2
|
import { assert, inspect } from '@ember/debug';
|
|
4
3
|
import EmberError from '@ember/error';
|
|
5
|
-
import { get
|
|
4
|
+
import { get } from '@ember/object';
|
|
6
5
|
import { _backburner as emberBackburner, cancel, run } from '@ember/runloop';
|
|
7
6
|
import { DEBUG } from '@glimmer/env';
|
|
8
7
|
|
|
9
8
|
import RSVP, { Promise } from 'rsvp';
|
|
10
9
|
|
|
11
|
-
import {
|
|
12
|
-
CUSTOM_MODEL_CLASS,
|
|
13
|
-
RECORD_DATA_ERRORS,
|
|
14
|
-
RECORD_DATA_STATE,
|
|
15
|
-
REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT,
|
|
16
|
-
REQUEST_SERVICE,
|
|
17
|
-
} from '@ember-data/canary-features';
|
|
18
10
|
import { HAS_MODEL_PACKAGE, HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
|
|
19
11
|
import type {
|
|
20
12
|
BelongsToRelationship,
|
|
@@ -31,15 +23,13 @@ import type { JsonApiResource, JsonApiValidationError } from '../../ts-interface
|
|
|
31
23
|
import type { RecordInstance } from '../../ts-interfaces/record-instance';
|
|
32
24
|
import type { FindOptions } from '../../ts-interfaces/store';
|
|
33
25
|
import type { ConfidentDict } from '../../ts-interfaces/utils';
|
|
34
|
-
import coerceId from '../coerce-id';
|
|
35
26
|
import type CoreStore from '../core-store';
|
|
36
27
|
import type Store from '../ds-model-store';
|
|
37
28
|
import { errorsHashToArray } from '../errors-utils';
|
|
38
|
-
import { recordArraysForIdentifier } from '../record-array-manager';
|
|
39
29
|
import recordDataFor from '../record-data-for';
|
|
40
30
|
import { BelongsToReference, HasManyReference, RecordReference } from '../references';
|
|
41
31
|
import Snapshot from '../snapshot';
|
|
42
|
-
import { internalModelFactoryFor
|
|
32
|
+
import { internalModelFactoryFor } from '../store/internal-model-factory';
|
|
43
33
|
import RootState from './states';
|
|
44
34
|
|
|
45
35
|
// move to TS hacks module that we can delete when this is no longer a necessary recast
|
|
@@ -72,11 +62,6 @@ if (HAS_MODEL_PACKAGE) {
|
|
|
72
62
|
};
|
|
73
63
|
}
|
|
74
64
|
|
|
75
|
-
// TODO this should be integrated with the code removal so we can use it together with the if condition
|
|
76
|
-
// and not alongside it
|
|
77
|
-
function isNotCustomModelClass(store: CoreStore | Store): store is Store {
|
|
78
|
-
return !CUSTOM_MODEL_CLASS;
|
|
79
|
-
}
|
|
80
65
|
interface BelongsToMetaWrapper {
|
|
81
66
|
key: string;
|
|
82
67
|
store: CoreStore;
|
|
@@ -233,60 +218,40 @@ export default class InternalModel {
|
|
|
233
218
|
return true;
|
|
234
219
|
}
|
|
235
220
|
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
return false;
|
|
239
|
-
}
|
|
221
|
+
if (this.currentState.isLoading) {
|
|
222
|
+
return false;
|
|
240
223
|
}
|
|
241
224
|
|
|
242
|
-
let isRecordFullyDeleted;
|
|
243
|
-
if (RECORD_DATA_STATE) {
|
|
244
|
-
isRecordFullyDeleted = this._isRecordFullyDeleted();
|
|
245
|
-
} else {
|
|
246
|
-
isRecordFullyDeleted = this.currentState.stateName === 'root.deleted.saved';
|
|
247
|
-
}
|
|
225
|
+
let isRecordFullyDeleted = this._isRecordFullyDeleted();
|
|
248
226
|
return this._isDematerializing || this.hasScheduledDestroy() || this.isDestroyed || isRecordFullyDeleted;
|
|
249
227
|
}
|
|
250
228
|
|
|
251
229
|
_isRecordFullyDeleted(): boolean {
|
|
252
|
-
if (
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return true;
|
|
262
|
-
} else {
|
|
263
|
-
return this.currentState.stateName === 'root.deleted.saved';
|
|
264
|
-
}
|
|
230
|
+
if (this._recordData.isDeletionCommitted && this._recordData.isDeletionCommitted()) {
|
|
231
|
+
return true;
|
|
232
|
+
} else if (
|
|
233
|
+
this._recordData.isNew &&
|
|
234
|
+
this._recordData.isDeleted &&
|
|
235
|
+
this._recordData.isNew() &&
|
|
236
|
+
this._recordData.isDeleted()
|
|
237
|
+
) {
|
|
238
|
+
return true;
|
|
265
239
|
} else {
|
|
266
|
-
|
|
267
|
-
return false;
|
|
240
|
+
return this.currentState.stateName === 'root.deleted.saved';
|
|
268
241
|
}
|
|
269
242
|
}
|
|
270
243
|
|
|
271
244
|
isDeleted() {
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
return this._recordData.isDeleted();
|
|
275
|
-
} else {
|
|
276
|
-
return this.currentState.isDeleted;
|
|
277
|
-
}
|
|
245
|
+
if (this._recordData.isDeleted) {
|
|
246
|
+
return this._recordData.isDeleted();
|
|
278
247
|
} else {
|
|
279
248
|
return this.currentState.isDeleted;
|
|
280
249
|
}
|
|
281
250
|
}
|
|
282
251
|
|
|
283
252
|
isNew() {
|
|
284
|
-
if (
|
|
285
|
-
|
|
286
|
-
return this._recordData.isNew();
|
|
287
|
-
} else {
|
|
288
|
-
return this.currentState.isNew;
|
|
289
|
-
}
|
|
253
|
+
if (this._recordData.isNew) {
|
|
254
|
+
return this._recordData.isNew();
|
|
290
255
|
} else {
|
|
291
256
|
return this.currentState.isNew;
|
|
292
257
|
}
|
|
@@ -296,73 +261,7 @@ export default class InternalModel {
|
|
|
296
261
|
if (!this._record && !this._isDematerializing) {
|
|
297
262
|
let { store } = this;
|
|
298
263
|
|
|
299
|
-
|
|
300
|
-
this._record = store._instantiateRecord(this, this.modelName, this._recordData, this.identifier, properties);
|
|
301
|
-
} else {
|
|
302
|
-
if (isNotCustomModelClass(store)) {
|
|
303
|
-
// lookupFactory should really return an object that creates
|
|
304
|
-
// instances with the injections applied
|
|
305
|
-
let createOptions: any = {
|
|
306
|
-
store,
|
|
307
|
-
_internalModel: this,
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
if (!REQUEST_SERVICE) {
|
|
311
|
-
createOptions.isError = this.isError;
|
|
312
|
-
createOptions.adapterError = this.error;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (properties !== undefined) {
|
|
316
|
-
assert(
|
|
317
|
-
`You passed '${properties}' as properties for record creation instead of an object.`,
|
|
318
|
-
typeof properties === 'object' && properties !== null
|
|
319
|
-
);
|
|
320
|
-
|
|
321
|
-
if ('id' in properties) {
|
|
322
|
-
const id = coerceId(properties.id);
|
|
323
|
-
|
|
324
|
-
if (id !== null) {
|
|
325
|
-
this.setId(id);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// convert relationship Records to RecordDatas before passing to RecordData
|
|
330
|
-
let defs = store._relationshipsDefinitionFor(this.modelName);
|
|
331
|
-
|
|
332
|
-
if (defs !== null) {
|
|
333
|
-
let keys = Object.keys(properties);
|
|
334
|
-
let relationshipValue;
|
|
335
|
-
|
|
336
|
-
for (let i = 0; i < keys.length; i++) {
|
|
337
|
-
let prop = keys[i];
|
|
338
|
-
let def = defs[prop];
|
|
339
|
-
|
|
340
|
-
if (def !== undefined) {
|
|
341
|
-
if (def.kind === 'hasMany') {
|
|
342
|
-
if (DEBUG) {
|
|
343
|
-
assertRecordsPassedToHasMany(properties[prop]);
|
|
344
|
-
}
|
|
345
|
-
relationshipValue = extractRecordDatasFromRecords(properties[prop]);
|
|
346
|
-
} else {
|
|
347
|
-
relationshipValue = extractRecordDataFromRecord(properties[prop]);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
properties[prop] = relationshipValue;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
let additionalCreateOptions = this._recordData._initRecordCreateOptions(properties);
|
|
357
|
-
Object.assign(createOptions, additionalCreateOptions);
|
|
358
|
-
|
|
359
|
-
// ensure that `getOwner(this)` works inside a model instance
|
|
360
|
-
setOwner(createOptions, getOwner(store));
|
|
361
|
-
|
|
362
|
-
this._record = store._modelFactoryFor(this.modelName).create(createOptions);
|
|
363
|
-
setRecordIdentifier(this._record, this.identifier);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
264
|
+
this._record = store._instantiateRecord(this, this.modelName, this._recordData, this.identifier, properties);
|
|
366
265
|
this._triggerDeferredTriggers();
|
|
367
266
|
}
|
|
368
267
|
|
|
@@ -377,15 +276,8 @@ export default class InternalModel {
|
|
|
377
276
|
this._doNotDestroy = false;
|
|
378
277
|
// this has to occur before the internal model is removed
|
|
379
278
|
// for legacy compat.
|
|
380
|
-
if (!REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT) {
|
|
381
|
-
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
382
|
-
}
|
|
383
279
|
if (this._record) {
|
|
384
|
-
|
|
385
|
-
this.store.teardownRecord(this._record);
|
|
386
|
-
} else {
|
|
387
|
-
this._record.destroy();
|
|
388
|
-
}
|
|
280
|
+
this.store.teardownRecord(this._record);
|
|
389
281
|
}
|
|
390
282
|
|
|
391
283
|
// move to an empty never-loaded state
|
|
@@ -409,19 +301,15 @@ export default class InternalModel {
|
|
|
409
301
|
this.error = null;
|
|
410
302
|
this._previousState = this.currentState;
|
|
411
303
|
this.currentState = RootState.empty;
|
|
412
|
-
|
|
413
|
-
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
414
|
-
}
|
|
304
|
+
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
415
305
|
}
|
|
416
306
|
|
|
417
307
|
deleteRecord() {
|
|
418
308
|
run(() => {
|
|
419
309
|
const backburner = this.store._backburner;
|
|
420
310
|
backburner.run(() => {
|
|
421
|
-
if (
|
|
422
|
-
|
|
423
|
-
this._recordData.setIsDeleted(true);
|
|
424
|
-
}
|
|
311
|
+
if (this._recordData.setIsDeleted) {
|
|
312
|
+
this._recordData.setIsDeleted(true);
|
|
425
313
|
}
|
|
426
314
|
|
|
427
315
|
if (this.isNew()) {
|
|
@@ -444,50 +332,26 @@ export default class InternalModel {
|
|
|
444
332
|
let promiseLabel = 'DS: Model#save ' + this;
|
|
445
333
|
let resolver = RSVP.defer<void>(promiseLabel);
|
|
446
334
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
return this.store.scheduleSave(this, resolver, options) as Promise<void>;
|
|
450
|
-
} else {
|
|
451
|
-
this.store.scheduleSave(this, resolver, options);
|
|
452
|
-
return resolver.promise;
|
|
453
|
-
}
|
|
335
|
+
// Casting to promise to narrow due to the feature flag paths inside scheduleSave
|
|
336
|
+
return this.store.scheduleSave(this, resolver, options) as Promise<void>;
|
|
454
337
|
}
|
|
455
338
|
|
|
456
339
|
reload(options) {
|
|
457
|
-
if (
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
);
|
|
473
|
-
} else {
|
|
474
|
-
let internalModel = this;
|
|
475
|
-
let promiseLabel = 'DS: Model#reload of ' + this;
|
|
476
|
-
|
|
477
|
-
return new Promise(function (resolve) {
|
|
478
|
-
internalModel.send('reloadRecord', { resolve, options });
|
|
479
|
-
}, promiseLabel).then(
|
|
480
|
-
function () {
|
|
481
|
-
internalModel.didCleanError();
|
|
482
|
-
return internalModel;
|
|
483
|
-
},
|
|
484
|
-
function (error) {
|
|
485
|
-
internalModel.didError(error);
|
|
486
|
-
throw error;
|
|
487
|
-
},
|
|
488
|
-
'DS: Model#reload complete, update flags'
|
|
489
|
-
);
|
|
490
|
-
}
|
|
340
|
+
if (!options) {
|
|
341
|
+
options = {};
|
|
342
|
+
}
|
|
343
|
+
let internalModel = this;
|
|
344
|
+
|
|
345
|
+
return internalModel.store._reloadRecord(internalModel, options).then(
|
|
346
|
+
function () {
|
|
347
|
+
//TODO NOW seems like we shouldn't need to do this
|
|
348
|
+
return internalModel;
|
|
349
|
+
},
|
|
350
|
+
function (error) {
|
|
351
|
+
throw error;
|
|
352
|
+
},
|
|
353
|
+
'DS: Model#reload complete, update flags'
|
|
354
|
+
);
|
|
491
355
|
}
|
|
492
356
|
|
|
493
357
|
/*
|
|
@@ -575,6 +439,8 @@ export default class InternalModel {
|
|
|
575
439
|
let identifier =
|
|
576
440
|
resource && resource.data ? identifierCacheFor(this.store).getOrCreateRecordIdentifier(resource.data) : null;
|
|
577
441
|
let relationshipMeta = this.store._relationshipMetaFor(this.modelName, null, key);
|
|
442
|
+
if (!relationshipMeta) return;
|
|
443
|
+
|
|
578
444
|
let store = this.store;
|
|
579
445
|
let parentInternalModel = this;
|
|
580
446
|
let async = relationshipMeta.options.async;
|
|
@@ -865,31 +731,17 @@ export default class InternalModel {
|
|
|
865
731
|
}
|
|
866
732
|
|
|
867
733
|
hasChangedAttributes() {
|
|
868
|
-
if (
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
return false;
|
|
872
|
-
}
|
|
873
|
-
} else {
|
|
874
|
-
if (this.currentState.isLoading) {
|
|
875
|
-
// no need to calculate changed attributes when calling `findRecord`
|
|
876
|
-
return false;
|
|
877
|
-
}
|
|
734
|
+
if (!this.__recordData) {
|
|
735
|
+
// no need to calculate changed attributes when calling `findRecord`
|
|
736
|
+
return false;
|
|
878
737
|
}
|
|
879
738
|
return this._recordData.hasChangedAttributes();
|
|
880
739
|
}
|
|
881
740
|
|
|
882
741
|
changedAttributes() {
|
|
883
|
-
if (
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
return {};
|
|
887
|
-
}
|
|
888
|
-
} else {
|
|
889
|
-
if (this.currentState.isLoading) {
|
|
890
|
-
// no need to calculate changed attributes when calling `findRecord`
|
|
891
|
-
return {};
|
|
892
|
-
}
|
|
742
|
+
if (!this.__recordData) {
|
|
743
|
+
// no need to calculate changed attributes when calling `findRecord`
|
|
744
|
+
return {};
|
|
893
745
|
}
|
|
894
746
|
return this._recordData.changedAttributes();
|
|
895
747
|
}
|
|
@@ -924,64 +776,29 @@ export default class InternalModel {
|
|
|
924
776
|
return;
|
|
925
777
|
}
|
|
926
778
|
|
|
927
|
-
|
|
928
|
-
this.store._notificationManager.notify(this.identifier, 'relationships', key);
|
|
929
|
-
} else {
|
|
930
|
-
if (manyArray) {
|
|
931
|
-
manyArray.notify();
|
|
932
|
-
|
|
933
|
-
//We need to notifyPropertyChange in the adding case because we need to make sure
|
|
934
|
-
//we fetch the newly added record in case it is unloaded
|
|
935
|
-
//TODO(Igor): Consider whether we could do this only if the record state is unloaded
|
|
936
|
-
if (manyArray.isAsync) {
|
|
937
|
-
this._record.notifyPropertyChange(key);
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
}
|
|
779
|
+
this.store._notificationManager.notify(this.identifier, 'relationships', key);
|
|
941
780
|
}
|
|
942
781
|
}
|
|
943
782
|
|
|
944
783
|
notifyBelongsToChange(key: string) {
|
|
945
784
|
if (this.hasRecord) {
|
|
946
|
-
|
|
947
|
-
this.store._notificationManager.notify(this.identifier, 'relationships', key);
|
|
948
|
-
} else {
|
|
949
|
-
this._record.notifyPropertyChange(key, this._record);
|
|
950
|
-
}
|
|
785
|
+
this.store._notificationManager.notify(this.identifier, 'relationships', key);
|
|
951
786
|
}
|
|
952
787
|
}
|
|
953
788
|
|
|
954
789
|
notifyPropertyChange(key) {
|
|
955
790
|
if (this.hasRecord) {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
this.store._notificationManager.notify(this.identifier, 'property', key);
|
|
962
|
-
} else {
|
|
963
|
-
if (key === 'currentState') {
|
|
964
|
-
set(this._record, 'currentState', this.currentState);
|
|
965
|
-
} else {
|
|
966
|
-
this._record.notifyPropertyChange(key);
|
|
967
|
-
}
|
|
968
|
-
}
|
|
791
|
+
// TODO this should likely *mostly* be the `attributes` bucket
|
|
792
|
+
// but it seems for local mutations we rely on computed updating
|
|
793
|
+
// iteself when set. As we design our own thing we may need to change
|
|
794
|
+
// that.
|
|
795
|
+
this.store._notificationManager.notify(this.identifier, 'property', key);
|
|
969
796
|
}
|
|
970
797
|
}
|
|
971
798
|
|
|
972
799
|
notifyStateChange(key?) {
|
|
973
|
-
assert('Cannot notify state change if Record Data State flag is not on', !!RECORD_DATA_STATE);
|
|
974
800
|
if (this.hasRecord) {
|
|
975
|
-
|
|
976
|
-
this.store._notificationManager.notify(this.identifier, 'state');
|
|
977
|
-
} else {
|
|
978
|
-
if (!key || key === 'isNew') {
|
|
979
|
-
(this.getRecord() as DSModel).notifyPropertyChange('isNew');
|
|
980
|
-
}
|
|
981
|
-
if (!key || key === 'isDeleted') {
|
|
982
|
-
(this.getRecord() as DSModel).notifyPropertyChange('isDeleted');
|
|
983
|
-
}
|
|
984
|
-
}
|
|
801
|
+
this.store._notificationManager.notify(this.identifier, 'state');
|
|
985
802
|
}
|
|
986
803
|
if (!key || key === 'isDeletionCommitted') {
|
|
987
804
|
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
@@ -1057,17 +874,13 @@ export default class InternalModel {
|
|
|
1057
874
|
}
|
|
1058
875
|
|
|
1059
876
|
this.currentState = state;
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
// this._record.notifyPropertyChange('currentState');
|
|
1068
|
-
}
|
|
1069
|
-
} else {
|
|
1070
|
-
this.notifyPropertyChange('currentState');
|
|
877
|
+
if (this.hasRecord && typeof this._record.notifyPropertyChange === 'function') {
|
|
878
|
+
// TODO refactor Model to have all flags pull from the notification manager
|
|
879
|
+
// and for currentState.stateName to be constructed from flag state.
|
|
880
|
+
// Probably just port this work from ember-m3
|
|
881
|
+
// After that we can eliminate this.
|
|
882
|
+
this.notifyStateChange('currentState');
|
|
883
|
+
// this._record.notifyPropertyChange('currentState');
|
|
1071
884
|
}
|
|
1072
885
|
|
|
1073
886
|
for (i = 0, l = setups.length; i < l; i++) {
|
|
@@ -1218,42 +1031,14 @@ export default class InternalModel {
|
|
|
1218
1031
|
}
|
|
1219
1032
|
|
|
1220
1033
|
if (didChange && this.hasRecord) {
|
|
1221
|
-
|
|
1222
|
-
this.store._notificationManager.notify(this.identifier, 'identity');
|
|
1223
|
-
} else {
|
|
1224
|
-
this.notifyPropertyChange('id');
|
|
1225
|
-
}
|
|
1034
|
+
this.store._notificationManager.notify(this.identifier, 'identity');
|
|
1226
1035
|
}
|
|
1227
1036
|
this._isUpdatingId = false;
|
|
1228
1037
|
}
|
|
1229
1038
|
|
|
1230
|
-
didError(
|
|
1231
|
-
if (!REQUEST_SERVICE) {
|
|
1232
|
-
this.error = error;
|
|
1233
|
-
this.isError = true;
|
|
1234
|
-
|
|
1235
|
-
if (this.hasRecord) {
|
|
1236
|
-
this._record.setProperties({
|
|
1237
|
-
isError: true,
|
|
1238
|
-
adapterError: error,
|
|
1239
|
-
});
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1039
|
+
didError() {}
|
|
1243
1040
|
|
|
1244
|
-
didCleanError() {
|
|
1245
|
-
if (!REQUEST_SERVICE) {
|
|
1246
|
-
this.error = null;
|
|
1247
|
-
this.isError = false;
|
|
1248
|
-
|
|
1249
|
-
if (this.hasRecord) {
|
|
1250
|
-
this._record.setProperties({
|
|
1251
|
-
isError: false,
|
|
1252
|
-
adapterError: null,
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1041
|
+
didCleanError() {}
|
|
1257
1042
|
|
|
1258
1043
|
/*
|
|
1259
1044
|
If the adapter did not return a hash in response to a commit,
|
|
@@ -1263,29 +1048,19 @@ export default class InternalModel {
|
|
|
1263
1048
|
adapterDidCommit(data) {
|
|
1264
1049
|
this.didCleanError();
|
|
1265
1050
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1051
|
+
this._recordData.didCommit(data);
|
|
1268
1052
|
this.send('didCommit');
|
|
1269
1053
|
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
1270
1054
|
|
|
1271
1055
|
if (!data) {
|
|
1272
1056
|
return;
|
|
1273
1057
|
}
|
|
1274
|
-
|
|
1275
|
-
this.store._notificationManager.notify(this.identifier, 'attributes');
|
|
1276
|
-
} else {
|
|
1277
|
-
this._record._notifyProperties(changedKeys);
|
|
1278
|
-
}
|
|
1058
|
+
this.store._notificationManager.notify(this.identifier, 'attributes');
|
|
1279
1059
|
}
|
|
1280
1060
|
|
|
1281
1061
|
hasErrors() {
|
|
1282
|
-
if (
|
|
1283
|
-
|
|
1284
|
-
return this._recordData.getErrors(this.identifier).length > 0;
|
|
1285
|
-
} else {
|
|
1286
|
-
let errors = (this.getRecord() as DSModel).errors;
|
|
1287
|
-
return errors.length > 0;
|
|
1288
|
-
}
|
|
1062
|
+
if (this._recordData.getErrors) {
|
|
1063
|
+
return this._recordData.getErrors(this.identifier).length > 0;
|
|
1289
1064
|
} else {
|
|
1290
1065
|
let errors = (this.getRecord() as DSModel).errors;
|
|
1291
1066
|
return errors.length > 0;
|
|
@@ -1294,54 +1069,37 @@ export default class InternalModel {
|
|
|
1294
1069
|
|
|
1295
1070
|
// FOR USE DURING COMMIT PROCESS
|
|
1296
1071
|
adapterDidInvalidate(parsedErrors, error) {
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
if (
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1307
|
-
}
|
|
1072
|
+
// TODO @runspired this should be handled by RecordState
|
|
1073
|
+
// and errors should be dirtied but lazily fetch if at
|
|
1074
|
+
// all possible. We should only notify errors here.
|
|
1075
|
+
let attribute;
|
|
1076
|
+
if (error && parsedErrors) {
|
|
1077
|
+
if (!this._recordData.getErrors) {
|
|
1078
|
+
for (attribute in parsedErrors) {
|
|
1079
|
+
if (hasOwnProperty.call(parsedErrors, attribute)) {
|
|
1080
|
+
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1308
1081
|
}
|
|
1309
1082
|
}
|
|
1310
|
-
|
|
1311
|
-
let jsonApiErrors: JsonApiValidationError[] = errorsHashToArray(parsedErrors);
|
|
1312
|
-
this.send('becameInvalid');
|
|
1313
|
-
if (jsonApiErrors.length === 0) {
|
|
1314
|
-
jsonApiErrors = [{ title: 'Invalid Error', detail: '', source: { pointer: '/data' } }];
|
|
1315
|
-
}
|
|
1316
|
-
this._recordData.commitWasRejected(this.identifier, jsonApiErrors);
|
|
1317
|
-
} else {
|
|
1318
|
-
this.send('becameError');
|
|
1319
|
-
this._recordData.commitWasRejected(this.identifier);
|
|
1320
|
-
}
|
|
1321
|
-
} else {
|
|
1322
|
-
let attribute;
|
|
1323
|
-
|
|
1324
|
-
for (attribute in parsedErrors) {
|
|
1325
|
-
if (hasOwnProperty.call(parsedErrors, attribute)) {
|
|
1326
|
-
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1327
|
-
}
|
|
1328
1083
|
}
|
|
1329
1084
|
|
|
1085
|
+
let jsonApiErrors: JsonApiValidationError[] = errorsHashToArray(parsedErrors);
|
|
1330
1086
|
this.send('becameInvalid');
|
|
1331
|
-
|
|
1332
|
-
|
|
1087
|
+
if (jsonApiErrors.length === 0) {
|
|
1088
|
+
jsonApiErrors = [{ title: 'Invalid Error', detail: '', source: { pointer: '/data' } }];
|
|
1089
|
+
}
|
|
1090
|
+
this._recordData.commitWasRejected(this.identifier, jsonApiErrors);
|
|
1091
|
+
} else {
|
|
1092
|
+
this.send('becameError');
|
|
1093
|
+
this._recordData.commitWasRejected(this.identifier);
|
|
1333
1094
|
}
|
|
1334
1095
|
}
|
|
1335
1096
|
|
|
1336
1097
|
notifyErrorsChange() {
|
|
1337
|
-
|
|
1338
|
-
this.store._notificationManager.notify(this.identifier, 'errors');
|
|
1339
|
-
}
|
|
1098
|
+
this.store._notificationManager.notify(this.identifier, 'errors');
|
|
1340
1099
|
}
|
|
1341
1100
|
|
|
1342
|
-
adapterDidError(
|
|
1101
|
+
adapterDidError() {
|
|
1343
1102
|
this.send('becameError');
|
|
1344
|
-
this.didError(error);
|
|
1345
1103
|
|
|
1346
1104
|
this._recordData.commitWasRejected();
|
|
1347
1105
|
}
|
|
@@ -1388,16 +1146,6 @@ export default class InternalModel {
|
|
|
1388
1146
|
}
|
|
1389
1147
|
}
|
|
1390
1148
|
|
|
1391
|
-
// in production code, this is only accesssed in `record-array-manager`
|
|
1392
|
-
// if REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT is also false
|
|
1393
|
-
if (!REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT) {
|
|
1394
|
-
Object.defineProperty(InternalModel.prototype, '_recordArrays', {
|
|
1395
|
-
get() {
|
|
1396
|
-
return recordArraysForIdentifier(this.identifier);
|
|
1397
|
-
},
|
|
1398
|
-
});
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
1149
|
function handleCompletedRelationshipRequest(internalModel, key, relationship, value, error) {
|
|
1402
1150
|
delete internalModel._relationshipPromisesCache[key];
|
|
1403
1151
|
relationship.state.shouldForceReload = false;
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { assert } from '@ember/debug';
|
|
5
5
|
|
|
6
|
-
import { CUSTOM_MODEL_CLASS, REQUEST_SERVICE } from '@ember-data/canary-features';
|
|
7
6
|
/*
|
|
8
7
|
This file encapsulates the various states that a record can transition
|
|
9
8
|
through during its lifecycle.
|
|
@@ -432,11 +431,7 @@ createdState.uncommitted.rollback = function (internalModel) {
|
|
|
432
431
|
|
|
433
432
|
createdState.uncommitted.pushedData = function (internalModel) {
|
|
434
433
|
// TODO @runspired consider where to do this once we kill off state machine
|
|
435
|
-
|
|
436
|
-
internalModel.store._notificationManager.notify(internalModel.identifier, 'identity');
|
|
437
|
-
} else {
|
|
438
|
-
internalModel.notifyPropertyChange('id');
|
|
439
|
-
}
|
|
434
|
+
internalModel.store._notificationManager.notify(internalModel.identifier, 'identity');
|
|
440
435
|
internalModel.transitionTo('loaded.updated.uncommitted');
|
|
441
436
|
internalModel.triggerLater('didLoad');
|
|
442
437
|
};
|
|
@@ -500,9 +495,6 @@ const RootState = {
|
|
|
500
495
|
|
|
501
496
|
// EVENTS
|
|
502
497
|
loadingData(internalModel, promise) {
|
|
503
|
-
if (!REQUEST_SERVICE) {
|
|
504
|
-
internalModel._promiseProxy = promise;
|
|
505
|
-
}
|
|
506
498
|
internalModel.transitionTo('loading');
|
|
507
499
|
},
|
|
508
500
|
|
|
@@ -593,11 +585,7 @@ const RootState = {
|
|
|
593
585
|
internalModel.transitionTo('updated.inFlight');
|
|
594
586
|
},
|
|
595
587
|
|
|
596
|
-
reloadRecord(
|
|
597
|
-
if (!REQUEST_SERVICE) {
|
|
598
|
-
resolve(internalModel.store._reloadRecord(internalModel, options));
|
|
599
|
-
}
|
|
600
|
-
},
|
|
588
|
+
reloadRecord() {},
|
|
601
589
|
|
|
602
590
|
deleteRecord(internalModel) {
|
|
603
591
|
internalModel.transitionTo('deleted.uncommitted');
|