@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,18 +1,17 @@
|
|
|
1
|
+
import { DEBUG } from '@glimmer/env';
|
|
2
|
+
|
|
1
3
|
import { ModelSchema } from '../../ts-interfaces/ds-model';
|
|
2
4
|
import type { AttributeSchema, RelationshipSchema } from '../../ts-interfaces/record-data-schemas';
|
|
3
5
|
import type { Dict } from '../../ts-interfaces/utils';
|
|
4
6
|
import type CoreStore from '../core-store';
|
|
7
|
+
import WeakCache from '../weak-cache';
|
|
5
8
|
|
|
6
|
-
const AvailableShims = new
|
|
7
|
-
|
|
9
|
+
const AvailableShims = new WeakCache<CoreStore, Dict<ShimModelClass>>(DEBUG ? 'schema-shims' : '');
|
|
10
|
+
AvailableShims._generator = () => {
|
|
11
|
+
return Object.create(null) as Dict<ShimModelClass>;
|
|
12
|
+
};
|
|
8
13
|
export function getShimClass(store: CoreStore, modelName: string): ShimModelClass {
|
|
9
|
-
let shims = AvailableShims.
|
|
10
|
-
|
|
11
|
-
if (shims === undefined) {
|
|
12
|
-
shims = Object.create(null) as Dict<ShimModelClass>;
|
|
13
|
-
AvailableShims.set(store, shims);
|
|
14
|
-
}
|
|
15
|
-
|
|
14
|
+
let shims = AvailableShims.lookup(store);
|
|
16
15
|
let shim = shims[modelName];
|
|
17
16
|
if (shim === undefined) {
|
|
18
17
|
shim = shims[modelName] = new ShimModelClass(store, modelName);
|
|
@@ -37,8 +36,8 @@ export default class ShimModelClass implements ModelSchema {
|
|
|
37
36
|
constructor(private __store: CoreStore, public modelName: string) {}
|
|
38
37
|
|
|
39
38
|
get fields(): Map<string, 'attribute' | 'belongsTo' | 'hasMany'> {
|
|
40
|
-
let attrs = this.__store._attributesDefinitionFor(this.modelName);
|
|
41
|
-
let relationships = this.__store._relationshipsDefinitionFor(this.modelName);
|
|
39
|
+
let attrs = this.__store._attributesDefinitionFor({ type: this.modelName });
|
|
40
|
+
let relationships = this.__store._relationshipsDefinitionFor({ type: this.modelName });
|
|
42
41
|
let fields = new Map<string, 'attribute' | 'belongsTo' | 'hasMany'>();
|
|
43
42
|
Object.keys(attrs).forEach((key) => fields.set(key, 'attribute'));
|
|
44
43
|
Object.keys(relationships).forEach((key) => fields.set(key, relationships[key]!.kind));
|
|
@@ -46,17 +45,17 @@ export default class ShimModelClass implements ModelSchema {
|
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
get attributes(): Map<string, AttributeSchema> {
|
|
49
|
-
let attrs = this.__store._attributesDefinitionFor(this.modelName);
|
|
48
|
+
let attrs = this.__store._attributesDefinitionFor({ type: this.modelName });
|
|
50
49
|
return mapFromHash(attrs);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
get relationshipsByName(): Map<string, RelationshipSchema> {
|
|
54
|
-
let relationships = this.__store._relationshipsDefinitionFor(this.modelName);
|
|
53
|
+
let relationships = this.__store._relationshipsDefinitionFor({ type: this.modelName });
|
|
55
54
|
return mapFromHash(relationships);
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
eachAttribute<T>(callback: (this: T | undefined, key: string, attribute: AttributeSchema) => void, binding?: T) {
|
|
59
|
-
let attrDefs = this.__store._attributesDefinitionFor(this.modelName);
|
|
58
|
+
let attrDefs = this.__store._attributesDefinitionFor({ type: this.modelName });
|
|
60
59
|
Object.keys(attrDefs).forEach((key) => {
|
|
61
60
|
callback.call(binding, key, attrDefs[key] as AttributeSchema);
|
|
62
61
|
});
|
|
@@ -66,7 +65,7 @@ export default class ShimModelClass implements ModelSchema {
|
|
|
66
65
|
callback: (this: T | undefined, key: string, relationship: RelationshipSchema) => void,
|
|
67
66
|
binding?: T
|
|
68
67
|
) {
|
|
69
|
-
let relationshipDefs = this.__store._relationshipsDefinitionFor(this.modelName);
|
|
68
|
+
let relationshipDefs = this.__store._relationshipsDefinitionFor({ type: this.modelName });
|
|
70
69
|
Object.keys(relationshipDefs).forEach((key) => {
|
|
71
70
|
callback.call(binding, key, relationshipDefs[key] as RelationshipSchema);
|
|
72
71
|
});
|
|
@@ -76,7 +75,7 @@ export default class ShimModelClass implements ModelSchema {
|
|
|
76
75
|
callback: (this: T | undefined, key: string, relationship: RelationshipSchema) => void,
|
|
77
76
|
binding?: T
|
|
78
77
|
) {
|
|
79
|
-
let relationshipDefs = this.__store._relationshipsDefinitionFor(this.modelName);
|
|
78
|
+
let relationshipDefs = this.__store._relationshipsDefinitionFor({ type: this.modelName });
|
|
80
79
|
Object.keys(relationshipDefs).forEach((key) => {
|
|
81
80
|
if (relationshipDefs[key]!.type) {
|
|
82
81
|
callback.call(binding, key, relationshipDefs[key] as RelationshipSchema);
|
|
@@ -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');
|
|
@@ -6,32 +6,24 @@ import { A } from '@ember/array';
|
|
|
6
6
|
import { assert } from '@ember/debug';
|
|
7
7
|
import { get, set } from '@ember/object';
|
|
8
8
|
import { _backburner as emberBackburner } from '@ember/runloop';
|
|
9
|
-
|
|
10
|
-
import { REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT } from '@ember-data/canary-features';
|
|
9
|
+
import { DEBUG } from '@glimmer/env';
|
|
11
10
|
|
|
12
11
|
import isStableIdentifier from '../identifiers/is-stable-identifier';
|
|
13
12
|
import { AdapterPopulatedRecordArray, RecordArray } from './record-arrays';
|
|
14
13
|
import { internalModelFactoryFor } from './store/internal-model-factory';
|
|
14
|
+
import WeakCache from './weak-cache';
|
|
15
15
|
|
|
16
|
-
const RecordArraysCache = new
|
|
17
|
-
|
|
16
|
+
const RecordArraysCache = new WeakCache(DEBUG ? 'record-arrays' : '');
|
|
17
|
+
RecordArraysCache._generator = () => new Set();
|
|
18
18
|
export function recordArraysForIdentifier(identifierOrInternalModel) {
|
|
19
|
-
|
|
20
|
-
// return existing Set if exists
|
|
21
|
-
return RecordArraysCache.get(identifierOrInternalModel);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// returns workable Set instance
|
|
25
|
-
RecordArraysCache.set(identifierOrInternalModel, new Set());
|
|
26
|
-
return RecordArraysCache.get(identifierOrInternalModel);
|
|
19
|
+
return RecordArraysCache.lookup(identifierOrInternalModel);
|
|
27
20
|
}
|
|
28
21
|
|
|
29
22
|
const pendingForIdentifier = new Set([]);
|
|
30
|
-
const IMDematerializing = new WeakMap();
|
|
31
23
|
|
|
32
|
-
|
|
24
|
+
function getIdentifier(identifierOrInternalModel) {
|
|
33
25
|
let i = identifierOrInternalModel;
|
|
34
|
-
if (!
|
|
26
|
+
if (!isStableIdentifier(identifierOrInternalModel)) {
|
|
35
27
|
// identifier may actually be an internalModel
|
|
36
28
|
// but during materialization we will get an identifier that
|
|
37
29
|
// has already been removed from the identifiers cache yet
|
|
@@ -40,24 +32,9 @@ const getIdentifier = function getIdentifier(identifierOrInternalModel) {
|
|
|
40
32
|
}
|
|
41
33
|
|
|
42
34
|
return i;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT only
|
|
46
|
-
const peekIMCache = function peekIMCache(cache, identifier) {
|
|
47
|
-
if (!REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT) {
|
|
48
|
-
let im = IMDematerializing.get(identifier);
|
|
49
|
-
if (im === undefined) {
|
|
50
|
-
// if not im._isDematerializing
|
|
51
|
-
im = cache.peek(identifier);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return im;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return cache.peek(identifier);
|
|
58
|
-
};
|
|
35
|
+
}
|
|
59
36
|
|
|
60
|
-
|
|
37
|
+
function shouldIncludeInRecordArrays(store, identifier) {
|
|
61
38
|
const cache = internalModelFactoryFor(store);
|
|
62
39
|
const internalModel = cache.peek(identifier);
|
|
63
40
|
|
|
@@ -65,7 +42,7 @@ const shouldIncludeInRecordArrays = function shouldIncludeInRecordArrays(store,
|
|
|
65
42
|
return false;
|
|
66
43
|
}
|
|
67
44
|
return !internalModel.isHiddenFromRecordArrays();
|
|
68
|
-
}
|
|
45
|
+
}
|
|
69
46
|
|
|
70
47
|
/**
|
|
71
48
|
@class RecordArrayManager
|
|
@@ -351,14 +328,6 @@ class RecordArrayManager {
|
|
|
351
328
|
let modelName = identifier.type;
|
|
352
329
|
identifier = getIdentifier(identifier);
|
|
353
330
|
|
|
354
|
-
if (!REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT) {
|
|
355
|
-
const cache = internalModelFactoryFor(this.store);
|
|
356
|
-
const im = peekIMCache(cache, identifier);
|
|
357
|
-
if (im && im._isDematerializing) {
|
|
358
|
-
IMDematerializing.set(identifier, im);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
331
|
if (pendingForIdentifier.has(identifier)) {
|
|
363
332
|
return;
|
|
364
333
|
}
|
|
@@ -386,7 +355,7 @@ class RecordArrayManager {
|
|
|
386
355
|
}
|
|
387
356
|
}
|
|
388
357
|
|
|
389
|
-
|
|
358
|
+
function removeFromArray(array, item) {
|
|
390
359
|
let index = array.indexOf(item);
|
|
391
360
|
|
|
392
361
|
if (index !== -1) {
|
|
@@ -395,9 +364,9 @@ const removeFromArray = function removeFromArray(array, item) {
|
|
|
395
364
|
}
|
|
396
365
|
|
|
397
366
|
return false;
|
|
398
|
-
}
|
|
367
|
+
}
|
|
399
368
|
|
|
400
|
-
|
|
369
|
+
function updateLiveRecordArray(store, recordArray, identifiers) {
|
|
401
370
|
let identifiersToAdd = [];
|
|
402
371
|
let identifiersToRemove = [];
|
|
403
372
|
|
|
@@ -420,46 +389,28 @@ const updateLiveRecordArray = function updateLiveRecordArray(store, recordArray,
|
|
|
420
389
|
}
|
|
421
390
|
|
|
422
391
|
if (identifiersToAdd.length > 0) {
|
|
423
|
-
|
|
392
|
+
recordArray._pushIdentifiers(identifiersToAdd);
|
|
424
393
|
}
|
|
425
394
|
if (identifiersToRemove.length > 0) {
|
|
426
|
-
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
const pushIdentifiers = function pushIdentifiers(recordArray, identifiers, cache) {
|
|
431
|
-
if (!REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT && !recordArray._pushIdentifiers) {
|
|
432
|
-
// deprecate('not allowed to use this intimate api any more');
|
|
433
|
-
recordArray._pushInternalModels(identifiers.map((i) => peekIMCache(cache, i)));
|
|
434
|
-
} else {
|
|
435
|
-
recordArray._pushIdentifiers(identifiers);
|
|
395
|
+
recordArray._removeIdentifiers(identifiersToRemove);
|
|
436
396
|
}
|
|
437
|
-
}
|
|
438
|
-
const removeIdentifiers = function removeIdentifiers(recordArray, identifiers, cache) {
|
|
439
|
-
if (!REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT && !recordArray._removeIdentifiers) {
|
|
440
|
-
// deprecate('not allowed to use this intimate api any more');
|
|
441
|
-
recordArray._removeInternalModels(identifiers.map((i) => peekIMCache(cache, i)));
|
|
442
|
-
} else {
|
|
443
|
-
recordArray._removeIdentifiers(identifiers);
|
|
444
|
-
}
|
|
445
|
-
};
|
|
397
|
+
}
|
|
446
398
|
|
|
447
|
-
|
|
399
|
+
function removeFromAdapterPopulatedRecordArrays(store, identifiers) {
|
|
448
400
|
for (let i = 0; i < identifiers.length; i++) {
|
|
449
401
|
removeFromAll(store, identifiers[i]);
|
|
450
402
|
}
|
|
451
|
-
}
|
|
403
|
+
}
|
|
452
404
|
|
|
453
|
-
|
|
405
|
+
function removeFromAll(store, identifier) {
|
|
454
406
|
identifier = getIdentifier(identifier);
|
|
455
407
|
const recordArrays = recordArraysForIdentifier(identifier);
|
|
456
|
-
const cache = internalModelFactoryFor(store);
|
|
457
408
|
|
|
458
409
|
recordArrays.forEach(function (recordArray) {
|
|
459
|
-
|
|
410
|
+
recordArray._removeIdentifiers([identifier]);
|
|
460
411
|
});
|
|
461
412
|
|
|
462
413
|
recordArrays.clear();
|
|
463
|
-
}
|
|
414
|
+
}
|
|
464
415
|
|
|
465
416
|
export default RecordArrayManager;
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { A } from '@ember/array';
|
|
2
2
|
import { get } from '@ember/object';
|
|
3
|
-
import { once } from '@ember/runloop';
|
|
4
|
-
import { DEBUG } from '@glimmer/env';
|
|
5
|
-
|
|
6
|
-
import { DEPRECATE_EVENTED_API_USAGE } from '@ember-data/private-build-infra/deprecations';
|
|
7
3
|
|
|
8
4
|
import RecordArray from './record-array';
|
|
9
5
|
|
|
@@ -51,18 +47,13 @@ import RecordArray from './record-array';
|
|
|
51
47
|
@public
|
|
52
48
|
@extends RecordArray
|
|
53
49
|
*/
|
|
54
|
-
|
|
50
|
+
export default RecordArray.extend({
|
|
55
51
|
init() {
|
|
56
52
|
this.set('content', this.get('content') || A());
|
|
57
53
|
|
|
58
54
|
this._super(...arguments);
|
|
59
55
|
this.query = this.query || null;
|
|
60
56
|
this.links = this.links || null;
|
|
61
|
-
|
|
62
|
-
if (DEBUG) {
|
|
63
|
-
this._getDeprecatedEventedInfo = () =>
|
|
64
|
-
`AdapterPopulatedRecordArray containing ${this.modelName} for query: ${this.query}`;
|
|
65
|
-
}
|
|
66
57
|
},
|
|
67
58
|
|
|
68
59
|
replace() {
|
|
@@ -90,14 +81,6 @@ let AdapterPopulatedRecordArray = RecordArray.extend({
|
|
|
90
81
|
});
|
|
91
82
|
|
|
92
83
|
this.manager._associateWithRecordArray(identifiersOrInternalModels, this);
|
|
93
|
-
|
|
94
|
-
if (DEPRECATE_EVENTED_API_USAGE) {
|
|
95
|
-
let _hasDidLoad = DEBUG ? this._has('didLoad') : this.has('didLoad');
|
|
96
|
-
if (_hasDidLoad) {
|
|
97
|
-
// TODO: should triggering didLoad event be the last action of the runLoop?
|
|
98
|
-
once(this, 'trigger', 'didLoad');
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
84
|
},
|
|
102
85
|
|
|
103
86
|
/**
|
|
@@ -110,5 +93,3 @@ let AdapterPopulatedRecordArray = RecordArray.extend({
|
|
|
110
93
|
this._setObjects(identifiers, payload);
|
|
111
94
|
},
|
|
112
95
|
});
|
|
113
|
-
|
|
114
|
-
export default AdapterPopulatedRecordArray;
|
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import ArrayProxy from '@ember/array/proxy';
|
|
5
5
|
import { computed, get, set } from '@ember/object';
|
|
6
|
-
import { DEBUG } from '@glimmer/env';
|
|
7
6
|
|
|
8
7
|
import { Promise } from 'rsvp';
|
|
9
8
|
|
|
10
|
-
import DeprecatedEvented from '../deprecated-evented';
|
|
11
9
|
import { PromiseArray } from '../promise-proxies';
|
|
12
10
|
import SnapshotRecordArray from '../snapshot-record-array';
|
|
13
11
|
import { internalModelFactoryFor } from '../store/internal-model-factory';
|
|
@@ -28,17 +26,12 @@ function recordForIdentifier(store, identifier) {
|
|
|
28
26
|
@class RecordArray
|
|
29
27
|
@public
|
|
30
28
|
@extends Ember.ArrayProxy
|
|
31
|
-
@uses Ember.Evented
|
|
32
29
|
*/
|
|
33
30
|
|
|
34
|
-
let RecordArray = ArrayProxy.extend(
|
|
31
|
+
let RecordArray = ArrayProxy.extend({
|
|
35
32
|
init(args) {
|
|
36
33
|
this._super(args);
|
|
37
34
|
|
|
38
|
-
if (DEBUG) {
|
|
39
|
-
this._getDeprecatedEventedInfo = () => `RecordArray containing ${this.modelName}`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
35
|
/**
|
|
43
36
|
The array of client ids backing the record array. When a
|
|
44
37
|
record is requested from the record array, the record
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { assert } from '@ember/debug';
|
|
2
|
+
import { DEBUG } from '@glimmer/env';
|
|
2
3
|
|
|
3
4
|
import type { StableRecordIdentifier } from '../ts-interfaces/identifier';
|
|
4
5
|
import type { RecordData } from '../ts-interfaces/record-data';
|
|
6
|
+
import WeakCache from './weak-cache';
|
|
5
7
|
|
|
6
8
|
/*
|
|
7
9
|
* Returns the RecordData instance associated with a given
|
|
@@ -25,23 +27,23 @@ type Reference = { internalModel: InternalModel };
|
|
|
25
27
|
|
|
26
28
|
type Instance = StableRecordIdentifier | InternalModel | RecordData | DSModelOrSnapshot | Reference;
|
|
27
29
|
|
|
28
|
-
const
|
|
30
|
+
const RecordDataForIdentifierCache = new WeakCache<StableRecordIdentifier, RecordData>(DEBUG ? 'recordData' : '');
|
|
29
31
|
|
|
30
|
-
export function setRecordDataFor(identifier: StableRecordIdentifier, recordData: RecordData) {
|
|
31
|
-
assert(`Illegal set of identifier`, !
|
|
32
|
-
|
|
32
|
+
export function setRecordDataFor(identifier: StableRecordIdentifier, recordData: RecordData): void {
|
|
33
|
+
assert(`Illegal set of identifier`, !RecordDataForIdentifierCache.has(identifier));
|
|
34
|
+
RecordDataForIdentifierCache.set(identifier, recordData);
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
export function removeRecordDataFor(identifier) {
|
|
36
|
-
|
|
37
|
+
export function removeRecordDataFor(identifier: StableRecordIdentifier): void {
|
|
38
|
+
RecordDataForIdentifierCache.delete(identifier);
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export default function recordDataFor(instance: StableRecordIdentifier): RecordData | null;
|
|
40
42
|
export default function recordDataFor(instance: Instance): RecordData;
|
|
41
43
|
export default function recordDataFor(instance: object): null;
|
|
42
44
|
export default function recordDataFor(instance: Instance | object): RecordData | null {
|
|
43
|
-
if (
|
|
44
|
-
return
|
|
45
|
+
if (RecordDataForIdentifierCache.has(instance as StableRecordIdentifier)) {
|
|
46
|
+
return RecordDataForIdentifierCache.get(instance as StableRecordIdentifier) as RecordData;
|
|
45
47
|
}
|
|
46
48
|
let internalModel =
|
|
47
49
|
(instance as DSModelOrSnapshot)._internalModel || (instance as Reference).internalModel || instance;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DEBUG } from '@glimmer/env';
|
|
2
|
+
|
|
2
3
|
import type { RecordIdentifier, StableRecordIdentifier } from '../ts-interfaces/identifier';
|
|
3
4
|
import type CoreStore from './core-store';
|
|
5
|
+
import WeakCache from './weak-cache';
|
|
4
6
|
|
|
5
7
|
type UnsubscribeToken = Object;
|
|
6
8
|
|
|
7
|
-
const Cache = new
|
|
8
|
-
|
|
9
|
+
const Cache = new WeakCache<StableRecordIdentifier, Map<UnsubscribeToken, NotificationCallback>>(
|
|
10
|
+
DEBUG ? 'subscribers' : ''
|
|
11
|
+
);
|
|
12
|
+
Cache._generator = () => new Map();
|
|
13
|
+
const Tokens = new WeakCache<UnsubscribeToken, StableRecordIdentifier>(DEBUG ? 'identifier' : '');
|
|
9
14
|
|
|
10
15
|
export type NotificationType =
|
|
11
16
|
| 'attributes'
|
|
@@ -39,12 +44,8 @@ export default class NotificationManager {
|
|
|
39
44
|
constructor(private store: CoreStore) {}
|
|
40
45
|
|
|
41
46
|
subscribe(identifier: RecordIdentifier, callback: NotificationCallback): UnsubscribeToken {
|
|
42
|
-
let stableIdentifier =
|
|
43
|
-
let map = Cache.
|
|
44
|
-
if (map === undefined) {
|
|
45
|
-
map = new Map();
|
|
46
|
-
Cache.set(stableIdentifier, map);
|
|
47
|
-
}
|
|
47
|
+
let stableIdentifier = this.store.identifierCache.getOrCreateRecordIdentifier(identifier);
|
|
48
|
+
let map = Cache.lookup(stableIdentifier);
|
|
48
49
|
let unsubToken = {};
|
|
49
50
|
map.set(unsubToken, callback);
|
|
50
51
|
Tokens.set(unsubToken, stableIdentifier);
|
|
@@ -54,7 +55,7 @@ export default class NotificationManager {
|
|
|
54
55
|
notify(identifier: RecordIdentifier, value: 'attributes' | 'relationships' | 'property', key?: string): boolean;
|
|
55
56
|
notify(identifier: RecordIdentifier, value: 'errors' | 'meta' | 'identity' | 'unload' | 'state'): boolean;
|
|
56
57
|
notify(identifier: RecordIdentifier, value: NotificationType, key?: string): boolean {
|
|
57
|
-
let stableIdentifier =
|
|
58
|
+
let stableIdentifier = this.store.identifierCache.getOrCreateRecordIdentifier(identifier);
|
|
58
59
|
let callbackMap = Cache.get(stableIdentifier);
|
|
59
60
|
if (!callbackMap || !callbackMap.size) {
|
|
60
61
|
return false;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { deprecate } from '@ember/debug';
|
|
2
1
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
3
2
|
import { cached, tracked } from '@glimmer/tracking';
|
|
4
3
|
|
|
5
4
|
import { resolve } from 'rsvp';
|
|
6
5
|
|
|
7
|
-
import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
|
|
8
|
-
import { DEPRECATE_BELONGS_TO_REFERENCE_PUSH } from '@ember-data/private-build-infra/deprecations';
|
|
9
6
|
import type { BelongsToRelationship } from '@ember-data/record-data/-private';
|
|
10
7
|
import { assertPolymorphicType } from '@ember-data/store/-debug';
|
|
11
8
|
|
|
@@ -13,7 +10,7 @@ import { SingleResourceDocument } from '../../ts-interfaces/ember-data-json-api'
|
|
|
13
10
|
import { StableRecordIdentifier } from '../../ts-interfaces/identifier';
|
|
14
11
|
import CoreStore from '../core-store';
|
|
15
12
|
import { NotificationType, unsubscribe } from '../record-notification-manager';
|
|
16
|
-
import { internalModelFactoryFor,
|
|
13
|
+
import { internalModelFactoryFor, recordIdentifierFor } from '../store/internal-model-factory';
|
|
17
14
|
import RecordReference from './record';
|
|
18
15
|
import Reference from './reference';
|
|
19
16
|
|
|
@@ -57,26 +54,22 @@ export default class BelongsToReference extends Reference {
|
|
|
57
54
|
this.parent = parent!.recordReference;
|
|
58
55
|
this.parentIdentifier = parentIdentifier;
|
|
59
56
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
(
|
|
64
|
-
|
|
65
|
-
this._ref++;
|
|
66
|
-
}
|
|
57
|
+
this.#token = store._notificationManager.subscribe(
|
|
58
|
+
parentIdentifier,
|
|
59
|
+
(_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
|
|
60
|
+
if ((bucket === 'relationships' || bucket === 'property') && notifiedKey === key) {
|
|
61
|
+
this._ref++;
|
|
67
62
|
}
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
}
|
|
64
|
+
);
|
|
70
65
|
|
|
71
66
|
// TODO inverse
|
|
72
67
|
}
|
|
73
68
|
|
|
74
69
|
destroy() {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
unsubscribe(this.#relatedToken);
|
|
79
|
-
}
|
|
70
|
+
unsubscribe(this.#token);
|
|
71
|
+
if (this.#relatedToken) {
|
|
72
|
+
unsubscribe(this.#relatedToken);
|
|
80
73
|
}
|
|
81
74
|
}
|
|
82
75
|
|
|
@@ -147,17 +140,7 @@ export default class BelongsToReference extends Reference {
|
|
|
147
140
|
@return {String} The id of the record in this belongsTo relationship.
|
|
148
141
|
*/
|
|
149
142
|
id(): string | null {
|
|
150
|
-
|
|
151
|
-
return this._relatedIdentifier?.id || null;
|
|
152
|
-
}
|
|
153
|
-
let resource = this._resource();
|
|
154
|
-
if (resource && resource.data) {
|
|
155
|
-
const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resource.data);
|
|
156
|
-
|
|
157
|
-
return identifier.id;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return null;
|
|
143
|
+
return this._relatedIdentifier?.id || null;
|
|
161
144
|
}
|
|
162
145
|
|
|
163
146
|
_resource() {
|
|
@@ -210,46 +193,28 @@ export default class BelongsToReference extends Reference {
|
|
|
210
193
|
@param {Object|Promise} objectOrPromise a promise that resolves to a JSONAPI document object describing the new value of this relationship.
|
|
211
194
|
@return {Promise<record>} A promise that resolves with the new value in this belongs-to relationship.
|
|
212
195
|
*/
|
|
213
|
-
async push(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
record
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
234
|
-
assertPolymorphicType(
|
|
235
|
-
this.belongsToRelationship.identifier,
|
|
236
|
-
this.belongsToRelationship.definition,
|
|
237
|
-
recordIdentifierFor(record),
|
|
238
|
-
this.store
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
const { graph, identifier } = this.belongsToRelationship;
|
|
242
|
-
this.store._backburner.join(() => {
|
|
243
|
-
graph.push({
|
|
244
|
-
op: 'replaceRelatedRecord',
|
|
245
|
-
record: identifier,
|
|
246
|
-
field: this.key,
|
|
247
|
-
value: recordIdentifierFor(record),
|
|
248
|
-
});
|
|
196
|
+
async push(data: SingleResourceDocument | Promise<SingleResourceDocument>): Promise<Object> {
|
|
197
|
+
const jsonApiDoc = await resolve(data);
|
|
198
|
+
let record = this.store.push(jsonApiDoc);
|
|
199
|
+
|
|
200
|
+
assertPolymorphicType(
|
|
201
|
+
this.belongsToRelationship.identifier,
|
|
202
|
+
this.belongsToRelationship.definition,
|
|
203
|
+
recordIdentifierFor(record),
|
|
204
|
+
this.store
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const { graph, identifier } = this.belongsToRelationship;
|
|
208
|
+
this.store._backburner.join(() => {
|
|
209
|
+
graph.push({
|
|
210
|
+
op: 'replaceRelatedRecord',
|
|
211
|
+
record: identifier,
|
|
212
|
+
field: this.key,
|
|
213
|
+
value: recordIdentifierFor(record),
|
|
249
214
|
});
|
|
250
|
-
|
|
251
|
-
return record;
|
|
252
215
|
});
|
|
216
|
+
|
|
217
|
+
return record;
|
|
253
218
|
}
|
|
254
219
|
|
|
255
220
|
/**
|