@ember-data/store 4.2.0-beta.0 → 4.3.0
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/identifiers/cache.ts +3 -16
- package/addon/-private/identifiers/is-stable-identifier.ts +2 -2
- package/addon/-private/index.ts +1 -3
- package/addon/-private/system/core-store.ts +192 -958
- package/addon/-private/system/ds-model-store.ts +20 -111
- package/addon/-private/system/fetch-manager.ts +11 -5
- package/addon/-private/system/model/internal-model.ts +92 -345
- package/addon/-private/system/model/shim-model-class.ts +15 -16
- package/addon/-private/system/model/states.js +2 -14
- package/addon/-private/system/record-array-manager.js +21 -70
- package/addon/-private/system/record-arrays/adapter-populated-record-array.js +1 -20
- package/addon/-private/system/record-arrays/record-array.js +1 -8
- package/addon/-private/system/record-data-for.ts +10 -8
- package/addon/-private/system/record-notification-manager.ts +11 -10
- package/addon/-private/system/references/belongs-to.ts +32 -67
- package/addon/-private/system/references/has-many.ts +21 -41
- package/addon/-private/system/references/record.ts +15 -27
- package/addon/-private/system/references/reference.ts +4 -11
- package/addon/-private/system/schema-definition-service.ts +2 -2
- package/addon/-private/system/snapshot.ts +28 -48
- package/addon/-private/system/store/finders.js +2 -96
- package/addon/-private/system/store/internal-model-factory.ts +34 -28
- package/addon/-private/system/store/record-data-store-wrapper.ts +28 -36
- package/addon/-private/system/weak-cache.ts +125 -0
- package/addon/-private/ts-interfaces/fetch-manager.ts +4 -0
- package/addon/-private/ts-interfaces/identifier.ts +2 -2
- package/addon/-private/ts-interfaces/minimum-adapter-interface.ts +0 -1
- package/addon/-private/ts-interfaces/schema-definition-service.ts +2 -2
- package/package.json +16 -16
- package/addon/-private/system/deprecated-evented.js +0 -92
|
@@ -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,
|
|
@@ -23,7 +15,6 @@ import type {
|
|
|
23
15
|
} from '@ember-data/record-data/-private';
|
|
24
16
|
import type { UpgradedMeta } from '@ember-data/record-data/-private/graph/-edge-definition';
|
|
25
17
|
|
|
26
|
-
import { identifierCacheFor } from '../../identifiers/cache';
|
|
27
18
|
import { DSModel } from '../../ts-interfaces/ds-model';
|
|
28
19
|
import type { StableRecordIdentifier } from '../../ts-interfaces/identifier';
|
|
29
20
|
import type { RecordData } from '../../ts-interfaces/record-data';
|
|
@@ -31,15 +22,13 @@ import type { JsonApiResource, JsonApiValidationError } from '../../ts-interface
|
|
|
31
22
|
import type { RecordInstance } from '../../ts-interfaces/record-instance';
|
|
32
23
|
import type { FindOptions } from '../../ts-interfaces/store';
|
|
33
24
|
import type { ConfidentDict } from '../../ts-interfaces/utils';
|
|
34
|
-
import coerceId from '../coerce-id';
|
|
35
25
|
import type CoreStore from '../core-store';
|
|
36
26
|
import type Store from '../ds-model-store';
|
|
37
27
|
import { errorsHashToArray } from '../errors-utils';
|
|
38
|
-
import { recordArraysForIdentifier } from '../record-array-manager';
|
|
39
28
|
import recordDataFor from '../record-data-for';
|
|
40
29
|
import { BelongsToReference, HasManyReference, RecordReference } from '../references';
|
|
41
30
|
import Snapshot from '../snapshot';
|
|
42
|
-
import { internalModelFactoryFor
|
|
31
|
+
import { internalModelFactoryFor } from '../store/internal-model-factory';
|
|
43
32
|
import RootState from './states';
|
|
44
33
|
|
|
45
34
|
// move to TS hacks module that we can delete when this is no longer a necessary recast
|
|
@@ -72,11 +61,6 @@ if (HAS_MODEL_PACKAGE) {
|
|
|
72
61
|
};
|
|
73
62
|
}
|
|
74
63
|
|
|
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
64
|
interface BelongsToMetaWrapper {
|
|
81
65
|
key: string;
|
|
82
66
|
store: CoreStore;
|
|
@@ -189,7 +173,7 @@ export default class InternalModel {
|
|
|
189
173
|
set id(value: string | null) {
|
|
190
174
|
if (value !== this._id) {
|
|
191
175
|
let newIdentifier = { type: this.identifier.type, lid: this.identifier.lid, id: value };
|
|
192
|
-
|
|
176
|
+
this.store.identifierCache.updateRecordIdentifier(this.identifier, newIdentifier);
|
|
193
177
|
this.notifyPropertyChange('id');
|
|
194
178
|
}
|
|
195
179
|
}
|
|
@@ -233,60 +217,40 @@ export default class InternalModel {
|
|
|
233
217
|
return true;
|
|
234
218
|
}
|
|
235
219
|
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
return false;
|
|
239
|
-
}
|
|
220
|
+
if (this.currentState.isLoading) {
|
|
221
|
+
return false;
|
|
240
222
|
}
|
|
241
223
|
|
|
242
|
-
let isRecordFullyDeleted;
|
|
243
|
-
if (RECORD_DATA_STATE) {
|
|
244
|
-
isRecordFullyDeleted = this._isRecordFullyDeleted();
|
|
245
|
-
} else {
|
|
246
|
-
isRecordFullyDeleted = this.currentState.stateName === 'root.deleted.saved';
|
|
247
|
-
}
|
|
224
|
+
let isRecordFullyDeleted = this._isRecordFullyDeleted();
|
|
248
225
|
return this._isDematerializing || this.hasScheduledDestroy() || this.isDestroyed || isRecordFullyDeleted;
|
|
249
226
|
}
|
|
250
227
|
|
|
251
228
|
_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
|
-
}
|
|
229
|
+
if (this._recordData.isDeletionCommitted && this._recordData.isDeletionCommitted()) {
|
|
230
|
+
return true;
|
|
231
|
+
} else if (
|
|
232
|
+
this._recordData.isNew &&
|
|
233
|
+
this._recordData.isDeleted &&
|
|
234
|
+
this._recordData.isNew() &&
|
|
235
|
+
this._recordData.isDeleted()
|
|
236
|
+
) {
|
|
237
|
+
return true;
|
|
265
238
|
} else {
|
|
266
|
-
|
|
267
|
-
return false;
|
|
239
|
+
return this.currentState.stateName === 'root.deleted.saved';
|
|
268
240
|
}
|
|
269
241
|
}
|
|
270
242
|
|
|
271
243
|
isDeleted() {
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
return this._recordData.isDeleted();
|
|
275
|
-
} else {
|
|
276
|
-
return this.currentState.isDeleted;
|
|
277
|
-
}
|
|
244
|
+
if (this._recordData.isDeleted) {
|
|
245
|
+
return this._recordData.isDeleted();
|
|
278
246
|
} else {
|
|
279
247
|
return this.currentState.isDeleted;
|
|
280
248
|
}
|
|
281
249
|
}
|
|
282
250
|
|
|
283
251
|
isNew() {
|
|
284
|
-
if (
|
|
285
|
-
|
|
286
|
-
return this._recordData.isNew();
|
|
287
|
-
} else {
|
|
288
|
-
return this.currentState.isNew;
|
|
289
|
-
}
|
|
252
|
+
if (this._recordData.isNew) {
|
|
253
|
+
return this._recordData.isNew();
|
|
290
254
|
} else {
|
|
291
255
|
return this.currentState.isNew;
|
|
292
256
|
}
|
|
@@ -296,73 +260,7 @@ export default class InternalModel {
|
|
|
296
260
|
if (!this._record && !this._isDematerializing) {
|
|
297
261
|
let { store } = this;
|
|
298
262
|
|
|
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
|
-
}
|
|
263
|
+
this._record = store._instantiateRecord(this, this.modelName, this._recordData, this.identifier, properties);
|
|
366
264
|
this._triggerDeferredTriggers();
|
|
367
265
|
}
|
|
368
266
|
|
|
@@ -377,15 +275,8 @@ export default class InternalModel {
|
|
|
377
275
|
this._doNotDestroy = false;
|
|
378
276
|
// this has to occur before the internal model is removed
|
|
379
277
|
// for legacy compat.
|
|
380
|
-
if (!REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT) {
|
|
381
|
-
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
382
|
-
}
|
|
383
278
|
if (this._record) {
|
|
384
|
-
|
|
385
|
-
this.store.teardownRecord(this._record);
|
|
386
|
-
} else {
|
|
387
|
-
this._record.destroy();
|
|
388
|
-
}
|
|
279
|
+
this.store.teardownRecord(this._record);
|
|
389
280
|
}
|
|
390
281
|
|
|
391
282
|
// move to an empty never-loaded state
|
|
@@ -409,19 +300,15 @@ export default class InternalModel {
|
|
|
409
300
|
this.error = null;
|
|
410
301
|
this._previousState = this.currentState;
|
|
411
302
|
this.currentState = RootState.empty;
|
|
412
|
-
|
|
413
|
-
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
414
|
-
}
|
|
303
|
+
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
415
304
|
}
|
|
416
305
|
|
|
417
306
|
deleteRecord() {
|
|
418
307
|
run(() => {
|
|
419
308
|
const backburner = this.store._backburner;
|
|
420
309
|
backburner.run(() => {
|
|
421
|
-
if (
|
|
422
|
-
|
|
423
|
-
this._recordData.setIsDeleted(true);
|
|
424
|
-
}
|
|
310
|
+
if (this._recordData.setIsDeleted) {
|
|
311
|
+
this._recordData.setIsDeleted(true);
|
|
425
312
|
}
|
|
426
313
|
|
|
427
314
|
if (this.isNew()) {
|
|
@@ -444,50 +331,26 @@ export default class InternalModel {
|
|
|
444
331
|
let promiseLabel = 'DS: Model#save ' + this;
|
|
445
332
|
let resolver = RSVP.defer<void>(promiseLabel);
|
|
446
333
|
|
|
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
|
-
}
|
|
334
|
+
// Casting to promise to narrow due to the feature flag paths inside scheduleSave
|
|
335
|
+
return this.store.scheduleSave(this, resolver, options) as Promise<void>;
|
|
454
336
|
}
|
|
455
337
|
|
|
456
338
|
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
|
-
}
|
|
339
|
+
if (!options) {
|
|
340
|
+
options = {};
|
|
341
|
+
}
|
|
342
|
+
let internalModel = this;
|
|
343
|
+
|
|
344
|
+
return internalModel.store._reloadRecord(internalModel, options).then(
|
|
345
|
+
function () {
|
|
346
|
+
//TODO NOW seems like we shouldn't need to do this
|
|
347
|
+
return internalModel;
|
|
348
|
+
},
|
|
349
|
+
function (error) {
|
|
350
|
+
throw error;
|
|
351
|
+
},
|
|
352
|
+
'DS: Model#reload complete, update flags'
|
|
353
|
+
);
|
|
491
354
|
}
|
|
492
355
|
|
|
493
356
|
/*
|
|
@@ -573,8 +436,10 @@ export default class InternalModel {
|
|
|
573
436
|
getBelongsTo(key, options) {
|
|
574
437
|
let resource = (this._recordData as DefaultRecordData).getBelongsTo(key);
|
|
575
438
|
let identifier =
|
|
576
|
-
resource && resource.data ?
|
|
439
|
+
resource && resource.data ? this.store.identifierCache.getOrCreateRecordIdentifier(resource.data) : null;
|
|
577
440
|
let relationshipMeta = this.store._relationshipMetaFor(this.modelName, null, key);
|
|
441
|
+
if (!relationshipMeta) return;
|
|
442
|
+
|
|
578
443
|
let store = this.store;
|
|
579
444
|
let parentInternalModel = this;
|
|
580
445
|
let async = relationshipMeta.options.async;
|
|
@@ -865,31 +730,17 @@ export default class InternalModel {
|
|
|
865
730
|
}
|
|
866
731
|
|
|
867
732
|
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
|
-
}
|
|
733
|
+
if (!this.__recordData) {
|
|
734
|
+
// no need to calculate changed attributes when calling `findRecord`
|
|
735
|
+
return false;
|
|
878
736
|
}
|
|
879
737
|
return this._recordData.hasChangedAttributes();
|
|
880
738
|
}
|
|
881
739
|
|
|
882
740
|
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
|
-
}
|
|
741
|
+
if (!this.__recordData) {
|
|
742
|
+
// no need to calculate changed attributes when calling `findRecord`
|
|
743
|
+
return {};
|
|
893
744
|
}
|
|
894
745
|
return this._recordData.changedAttributes();
|
|
895
746
|
}
|
|
@@ -924,64 +775,29 @@ export default class InternalModel {
|
|
|
924
775
|
return;
|
|
925
776
|
}
|
|
926
777
|
|
|
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
|
-
}
|
|
778
|
+
this.store._notificationManager.notify(this.identifier, 'relationships', key);
|
|
941
779
|
}
|
|
942
780
|
}
|
|
943
781
|
|
|
944
782
|
notifyBelongsToChange(key: string) {
|
|
945
783
|
if (this.hasRecord) {
|
|
946
|
-
|
|
947
|
-
this.store._notificationManager.notify(this.identifier, 'relationships', key);
|
|
948
|
-
} else {
|
|
949
|
-
this._record.notifyPropertyChange(key, this._record);
|
|
950
|
-
}
|
|
784
|
+
this.store._notificationManager.notify(this.identifier, 'relationships', key);
|
|
951
785
|
}
|
|
952
786
|
}
|
|
953
787
|
|
|
954
788
|
notifyPropertyChange(key) {
|
|
955
789
|
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
|
-
}
|
|
790
|
+
// TODO this should likely *mostly* be the `attributes` bucket
|
|
791
|
+
// but it seems for local mutations we rely on computed updating
|
|
792
|
+
// iteself when set. As we design our own thing we may need to change
|
|
793
|
+
// that.
|
|
794
|
+
this.store._notificationManager.notify(this.identifier, 'property', key);
|
|
969
795
|
}
|
|
970
796
|
}
|
|
971
797
|
|
|
972
798
|
notifyStateChange(key?) {
|
|
973
|
-
assert('Cannot notify state change if Record Data State flag is not on', !!RECORD_DATA_STATE);
|
|
974
799
|
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
|
-
}
|
|
800
|
+
this.store._notificationManager.notify(this.identifier, 'state');
|
|
985
801
|
}
|
|
986
802
|
if (!key || key === 'isDeletionCommitted') {
|
|
987
803
|
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
@@ -1057,17 +873,13 @@ export default class InternalModel {
|
|
|
1057
873
|
}
|
|
1058
874
|
|
|
1059
875
|
this.currentState = state;
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
// this._record.notifyPropertyChange('currentState');
|
|
1068
|
-
}
|
|
1069
|
-
} else {
|
|
1070
|
-
this.notifyPropertyChange('currentState');
|
|
876
|
+
if (this.hasRecord && typeof this._record.notifyPropertyChange === 'function') {
|
|
877
|
+
// TODO refactor Model to have all flags pull from the notification manager
|
|
878
|
+
// and for currentState.stateName to be constructed from flag state.
|
|
879
|
+
// Probably just port this work from ember-m3
|
|
880
|
+
// After that we can eliminate this.
|
|
881
|
+
this.notifyStateChange('currentState');
|
|
882
|
+
// this._record.notifyPropertyChange('currentState');
|
|
1071
883
|
}
|
|
1072
884
|
|
|
1073
885
|
for (i = 0, l = setups.length; i < l; i++) {
|
|
@@ -1218,42 +1030,14 @@ export default class InternalModel {
|
|
|
1218
1030
|
}
|
|
1219
1031
|
|
|
1220
1032
|
if (didChange && this.hasRecord) {
|
|
1221
|
-
|
|
1222
|
-
this.store._notificationManager.notify(this.identifier, 'identity');
|
|
1223
|
-
} else {
|
|
1224
|
-
this.notifyPropertyChange('id');
|
|
1225
|
-
}
|
|
1033
|
+
this.store._notificationManager.notify(this.identifier, 'identity');
|
|
1226
1034
|
}
|
|
1227
1035
|
this._isUpdatingId = false;
|
|
1228
1036
|
}
|
|
1229
1037
|
|
|
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
|
-
}
|
|
1038
|
+
didError() {}
|
|
1243
1039
|
|
|
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
|
-
}
|
|
1040
|
+
didCleanError() {}
|
|
1257
1041
|
|
|
1258
1042
|
/*
|
|
1259
1043
|
If the adapter did not return a hash in response to a commit,
|
|
@@ -1263,29 +1047,19 @@ export default class InternalModel {
|
|
|
1263
1047
|
adapterDidCommit(data) {
|
|
1264
1048
|
this.didCleanError();
|
|
1265
1049
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1050
|
+
this._recordData.didCommit(data);
|
|
1268
1051
|
this.send('didCommit');
|
|
1269
1052
|
this.store.recordArrayManager.recordDidChange(this.identifier);
|
|
1270
1053
|
|
|
1271
1054
|
if (!data) {
|
|
1272
1055
|
return;
|
|
1273
1056
|
}
|
|
1274
|
-
|
|
1275
|
-
this.store._notificationManager.notify(this.identifier, 'attributes');
|
|
1276
|
-
} else {
|
|
1277
|
-
this._record._notifyProperties(changedKeys);
|
|
1278
|
-
}
|
|
1057
|
+
this.store._notificationManager.notify(this.identifier, 'attributes');
|
|
1279
1058
|
}
|
|
1280
1059
|
|
|
1281
1060
|
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
|
-
}
|
|
1061
|
+
if (this._recordData.getErrors) {
|
|
1062
|
+
return this._recordData.getErrors(this.identifier).length > 0;
|
|
1289
1063
|
} else {
|
|
1290
1064
|
let errors = (this.getRecord() as DSModel).errors;
|
|
1291
1065
|
return errors.length > 0;
|
|
@@ -1294,54 +1068,37 @@ export default class InternalModel {
|
|
|
1294
1068
|
|
|
1295
1069
|
// FOR USE DURING COMMIT PROCESS
|
|
1296
1070
|
adapterDidInvalidate(parsedErrors, error) {
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
if (
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1307
|
-
}
|
|
1071
|
+
// TODO @runspired this should be handled by RecordState
|
|
1072
|
+
// and errors should be dirtied but lazily fetch if at
|
|
1073
|
+
// all possible. We should only notify errors here.
|
|
1074
|
+
let attribute;
|
|
1075
|
+
if (error && parsedErrors) {
|
|
1076
|
+
if (!this._recordData.getErrors) {
|
|
1077
|
+
for (attribute in parsedErrors) {
|
|
1078
|
+
if (hasOwnProperty.call(parsedErrors, attribute)) {
|
|
1079
|
+
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1308
1080
|
}
|
|
1309
1081
|
}
|
|
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
1082
|
}
|
|
1329
1083
|
|
|
1084
|
+
let jsonApiErrors: JsonApiValidationError[] = errorsHashToArray(parsedErrors);
|
|
1330
1085
|
this.send('becameInvalid');
|
|
1331
|
-
|
|
1332
|
-
|
|
1086
|
+
if (jsonApiErrors.length === 0) {
|
|
1087
|
+
jsonApiErrors = [{ title: 'Invalid Error', detail: '', source: { pointer: '/data' } }];
|
|
1088
|
+
}
|
|
1089
|
+
this._recordData.commitWasRejected(this.identifier, jsonApiErrors);
|
|
1090
|
+
} else {
|
|
1091
|
+
this.send('becameError');
|
|
1092
|
+
this._recordData.commitWasRejected(this.identifier);
|
|
1333
1093
|
}
|
|
1334
1094
|
}
|
|
1335
1095
|
|
|
1336
1096
|
notifyErrorsChange() {
|
|
1337
|
-
|
|
1338
|
-
this.store._notificationManager.notify(this.identifier, 'errors');
|
|
1339
|
-
}
|
|
1097
|
+
this.store._notificationManager.notify(this.identifier, 'errors');
|
|
1340
1098
|
}
|
|
1341
1099
|
|
|
1342
|
-
adapterDidError(
|
|
1100
|
+
adapterDidError() {
|
|
1343
1101
|
this.send('becameError');
|
|
1344
|
-
this.didError(error);
|
|
1345
1102
|
|
|
1346
1103
|
this._recordData.commitWasRejected();
|
|
1347
1104
|
}
|
|
@@ -1388,16 +1145,6 @@ export default class InternalModel {
|
|
|
1388
1145
|
}
|
|
1389
1146
|
}
|
|
1390
1147
|
|
|
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
1148
|
function handleCompletedRelationshipRequest(internalModel, key, relationship, value, error) {
|
|
1402
1149
|
delete internalModel._relationshipPromisesCache[key];
|
|
1403
1150
|
relationship.state.shouldForceReload = false;
|