@ember-data/store 5.0.0-alpha.1 → 5.0.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.
|
@@ -1,40 +1,14 @@
|
|
|
1
|
-
import { macroCondition, getOwnConfig, importSync } from '@embroider/macros';
|
|
2
|
-
import { assert, warn, deprecate } from '@ember/debug';
|
|
3
|
-
import { dasherize } from '@ember/string';
|
|
4
1
|
import { getOwner, setOwner } from '@ember/application';
|
|
2
|
+
import { assert, warn } from '@ember/debug';
|
|
5
3
|
import { _backburner } from '@ember/runloop';
|
|
4
|
+
import { macroCondition, getOwnConfig, importSync } from '@embroider/macros';
|
|
6
5
|
import { tracked } from '@glimmer/tracking';
|
|
6
|
+
import { dasherize } from '@ember/string';
|
|
7
7
|
import { subscribe, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
|
|
8
8
|
import { tagForProperty } from '@ember/-internals/metal';
|
|
9
|
-
import { get, set } from '@ember/object';
|
|
10
9
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
11
|
-
import { compare } from '@ember/utils';
|
|
12
10
|
import { dirtyTag } from '@glimmer/validator';
|
|
13
11
|
import Ember from 'ember';
|
|
14
|
-
import { reads } from '@ember/object/computed';
|
|
15
|
-
import ArrayProxy from '@ember/array/proxy';
|
|
16
|
-
import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
|
|
17
|
-
import ObjectProxy from '@ember/object/proxy';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
@module @ember-data/store
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
This method normalizes a modelName into the format Ember Data uses
|
|
25
|
-
internally by dasherizing it.
|
|
26
|
-
|
|
27
|
-
@method normalizeModelName
|
|
28
|
-
@static
|
|
29
|
-
@public
|
|
30
|
-
@deprecated
|
|
31
|
-
@for @ember-data/store
|
|
32
|
-
@param {String} modelName
|
|
33
|
-
@return {String} normalizedModelName
|
|
34
|
-
*/
|
|
35
|
-
function normalizeModelName$1(modelName) {
|
|
36
|
-
return dasherize(modelName);
|
|
37
|
-
}
|
|
38
12
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
39
13
|
if (!descriptor) return;
|
|
40
14
|
Object.defineProperty(target, property, {
|
|
@@ -77,25 +51,25 @@ function _applyDecoratedDescriptor(target, property, decorators, descriptor, con
|
|
|
77
51
|
}
|
|
78
52
|
return desc;
|
|
79
53
|
}
|
|
80
|
-
var _class$
|
|
54
|
+
var _class$2, _descriptor$2, _descriptor2$1, _descriptor3, _descriptor4, _store, _request;
|
|
81
55
|
function urlFromLink(link) {
|
|
82
56
|
if (typeof link === 'string') return link;
|
|
83
57
|
return link.href;
|
|
84
58
|
}
|
|
85
|
-
let Document = (_class$
|
|
59
|
+
let Document = (_class$2 = (_store = /*#__PURE__*/_classPrivateFieldKey("store"), _request = /*#__PURE__*/_classPrivateFieldKey("request"), class Document {
|
|
86
60
|
constructor(store, identifier) {
|
|
87
61
|
Object.defineProperty(this, _request, {
|
|
88
62
|
value: _request2
|
|
89
63
|
});
|
|
90
|
-
_initializerDefineProperty(this, "links", _descriptor$
|
|
64
|
+
_initializerDefineProperty(this, "links", _descriptor$2, this);
|
|
91
65
|
_initializerDefineProperty(this, "data", _descriptor2$1, this);
|
|
92
66
|
_initializerDefineProperty(this, "errors", _descriptor3, this);
|
|
93
67
|
_initializerDefineProperty(this, "meta", _descriptor4, this);
|
|
94
|
-
Object.defineProperty(this, _store
|
|
68
|
+
Object.defineProperty(this, _store, {
|
|
95
69
|
writable: true,
|
|
96
70
|
value: void 0
|
|
97
71
|
});
|
|
98
|
-
_classPrivateFieldBase(this, _store
|
|
72
|
+
_classPrivateFieldBase(this, _store)[_store] = store;
|
|
99
73
|
this.identifier = identifier;
|
|
100
74
|
}
|
|
101
75
|
fetch(options = {}) {
|
|
@@ -133,33 +107,33 @@ let Document = (_class$3 = (_store$1 = /*#__PURE__*/_classPrivateFieldKey("store
|
|
|
133
107
|
}
|
|
134
108
|
return data;
|
|
135
109
|
}
|
|
136
|
-
}), (_descriptor$
|
|
110
|
+
}), (_descriptor$2 = _applyDecoratedDescriptor(_class$2.prototype, "links", [tracked], {
|
|
137
111
|
configurable: true,
|
|
138
112
|
enumerable: true,
|
|
139
113
|
writable: true,
|
|
140
114
|
initializer: null
|
|
141
|
-
}), _descriptor2$1 = _applyDecoratedDescriptor(_class$
|
|
115
|
+
}), _descriptor2$1 = _applyDecoratedDescriptor(_class$2.prototype, "data", [tracked], {
|
|
142
116
|
configurable: true,
|
|
143
117
|
enumerable: true,
|
|
144
118
|
writable: true,
|
|
145
119
|
initializer: null
|
|
146
|
-
}), _descriptor3 = _applyDecoratedDescriptor(_class$
|
|
120
|
+
}), _descriptor3 = _applyDecoratedDescriptor(_class$2.prototype, "errors", [tracked], {
|
|
147
121
|
configurable: true,
|
|
148
122
|
enumerable: true,
|
|
149
123
|
writable: true,
|
|
150
124
|
initializer: null
|
|
151
|
-
}), _descriptor4 = _applyDecoratedDescriptor(_class$
|
|
125
|
+
}), _descriptor4 = _applyDecoratedDescriptor(_class$2.prototype, "meta", [tracked], {
|
|
152
126
|
configurable: true,
|
|
153
127
|
enumerable: true,
|
|
154
128
|
writable: true,
|
|
155
129
|
initializer: null
|
|
156
|
-
})), _class$
|
|
130
|
+
})), _class$2);
|
|
157
131
|
async function _request2(link, options = {}) {
|
|
158
132
|
const href = this.links?.[link];
|
|
159
133
|
if (!href) {
|
|
160
134
|
return null;
|
|
161
135
|
}
|
|
162
|
-
const response = await _classPrivateFieldBase(this, _store
|
|
136
|
+
const response = await _classPrivateFieldBase(this, _store)[_store].request(Object.assign(options, {
|
|
163
137
|
url: urlFromLink(href)
|
|
164
138
|
}));
|
|
165
139
|
return response.content;
|
|
@@ -439,6 +413,9 @@ const DEBUG_IDENTIFIER_BUCKET = Symbol('identifier-bucket');
|
|
|
439
413
|
function isNonEmptyString(str) {
|
|
440
414
|
return str && typeof str === 'string';
|
|
441
415
|
}
|
|
416
|
+
function normalizeModelName(modelName) {
|
|
417
|
+
return dasherize(modelName);
|
|
418
|
+
}
|
|
442
419
|
|
|
443
420
|
/**
|
|
444
421
|
@module @ember-data/store
|
|
@@ -536,7 +513,7 @@ function defaultGenerationMethod(data, bucket) {
|
|
|
536
513
|
} = data;
|
|
537
514
|
// TODO: add test for id not a string
|
|
538
515
|
if (isNonEmptyString(coerceId(id))) {
|
|
539
|
-
return `@lid:${normalizeModelName
|
|
516
|
+
return `@lid:${normalizeModelName(type)}-${id}`;
|
|
540
517
|
}
|
|
541
518
|
}
|
|
542
519
|
return uuidv4();
|
|
@@ -641,7 +618,7 @@ class IdentifierCache {
|
|
|
641
618
|
|
|
642
619
|
// `type` must always be present
|
|
643
620
|
assert('resource.type needs to be a string', 'type' in resource && isNonEmptyString(resource.type));
|
|
644
|
-
let type = resource.type && normalizeModelName
|
|
621
|
+
let type = resource.type && normalizeModelName(resource.type);
|
|
645
622
|
let id = coerceId(resource.id);
|
|
646
623
|
let keyOptions = getTypeIndex(this._cache.types, type);
|
|
647
624
|
|
|
@@ -857,7 +834,7 @@ class IdentifierCache {
|
|
|
857
834
|
if (!existingIdentifier) {
|
|
858
835
|
// If the incoming type does not match the identifier type, we need to create an identifier for the incoming
|
|
859
836
|
// data so we can merge the incoming data with the existing identifier, see #7325 and #7363
|
|
860
|
-
if (data.type && identifier.type !== normalizeModelName
|
|
837
|
+
if (data.type && identifier.type !== normalizeModelName(data.type)) {
|
|
861
838
|
let incomingDataResource = {
|
|
862
839
|
...data
|
|
863
840
|
};
|
|
@@ -1019,7 +996,7 @@ function performRecordIdentifierUpdate(identifier, data, updateFn) {
|
|
|
1019
996
|
lid
|
|
1020
997
|
} = data;
|
|
1021
998
|
let id = 'id' in data ? data.id : undefined;
|
|
1022
|
-
let type = 'type' in data && data.type && normalizeModelName
|
|
999
|
+
let type = 'type' in data && data.type && normalizeModelName(data.type);
|
|
1023
1000
|
|
|
1024
1001
|
// get the mutable instance behind our proxy wrapper
|
|
1025
1002
|
let wrapper = identifier;
|
|
@@ -1069,7 +1046,7 @@ function detectMerge(typesCache, identifier, data, newId, lids) {
|
|
|
1069
1046
|
let existingIdentifier = keyOptions.id.get(newId);
|
|
1070
1047
|
return existingIdentifier !== undefined ? existingIdentifier : false;
|
|
1071
1048
|
} else {
|
|
1072
|
-
let newType = data.type && normalizeModelName
|
|
1049
|
+
let newType = data.type && normalizeModelName(data.type);
|
|
1073
1050
|
|
|
1074
1051
|
// If the ids and type are the same but lid is not the same, we should trigger a merge of the identifiers
|
|
1075
1052
|
if (id !== null && id === newId && newType === type && data.lid && data.lid !== lid) {
|
|
@@ -1282,7 +1259,7 @@ class NotificationManager {
|
|
|
1282
1259
|
Cache.clear();
|
|
1283
1260
|
}
|
|
1284
1261
|
}
|
|
1285
|
-
var _class$
|
|
1262
|
+
var _class$1, _descriptor$1;
|
|
1286
1263
|
/**
|
|
1287
1264
|
@module @ember-data/store
|
|
1288
1265
|
*/
|
|
@@ -1294,13 +1271,13 @@ var _class$2, _descriptor$2;
|
|
|
1294
1271
|
@public
|
|
1295
1272
|
@extends Reference
|
|
1296
1273
|
*/
|
|
1297
|
-
let RecordReference = (_class$
|
|
1274
|
+
let RecordReference = (_class$1 = class RecordReference {
|
|
1298
1275
|
// unsubscribe token given to us by the notification manager
|
|
1299
1276
|
|
|
1300
1277
|
constructor(store, identifier) {
|
|
1301
1278
|
this.___token = void 0;
|
|
1302
1279
|
this.___identifier = void 0;
|
|
1303
|
-
_initializerDefineProperty(this, "_ref", _descriptor$
|
|
1280
|
+
_initializerDefineProperty(this, "_ref", _descriptor$1, this);
|
|
1304
1281
|
this.store = store;
|
|
1305
1282
|
this.___identifier = identifier;
|
|
1306
1283
|
this.___token = store.notifications.subscribe(identifier, (_, bucket, notifiedKey) => {
|
|
@@ -1468,2342 +1445,1114 @@ let RecordReference = (_class$2 = class RecordReference {
|
|
|
1468
1445
|
}
|
|
1469
1446
|
assert(`Unable to fetch record of type ${this.type} without an id`);
|
|
1470
1447
|
}
|
|
1471
|
-
}, _descriptor$
|
|
1448
|
+
}, _descriptor$1 = _applyDecoratedDescriptor(_class$1.prototype, "_ref", [tracked], {
|
|
1472
1449
|
configurable: true,
|
|
1473
1450
|
enumerable: true,
|
|
1474
1451
|
writable: true,
|
|
1475
1452
|
initializer: function () {
|
|
1476
1453
|
return 0;
|
|
1477
1454
|
}
|
|
1478
|
-
}), _class$
|
|
1479
|
-
function legacyCachePut(store, doc) {
|
|
1480
|
-
const jsonApiDoc = doc.content;
|
|
1481
|
-
let ret;
|
|
1482
|
-
store._join(() => {
|
|
1483
|
-
let included = jsonApiDoc.included;
|
|
1484
|
-
let i, length;
|
|
1485
|
-
if (included) {
|
|
1486
|
-
for (i = 0, length = included.length; i < length; i++) {
|
|
1487
|
-
store._instanceCache.loadData(included[i]);
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
if (Array.isArray(jsonApiDoc.data)) {
|
|
1491
|
-
length = jsonApiDoc.data.length;
|
|
1492
|
-
let identifiers = [];
|
|
1493
|
-
for (i = 0; i < length; i++) {
|
|
1494
|
-
identifiers.push(store._instanceCache.loadData(jsonApiDoc.data[i]));
|
|
1495
|
-
}
|
|
1496
|
-
ret = {
|
|
1497
|
-
data: identifiers
|
|
1498
|
-
};
|
|
1499
|
-
return;
|
|
1500
|
-
}
|
|
1501
|
-
if (jsonApiDoc.data === null) {
|
|
1502
|
-
ret = {
|
|
1503
|
-
data: null
|
|
1504
|
-
};
|
|
1505
|
-
return;
|
|
1506
|
-
}
|
|
1507
|
-
assert(`Expected an object in the 'data' property in a call to 'push', but was ${typeof jsonApiDoc.data}`, typeof jsonApiDoc.data === 'object');
|
|
1508
|
-
ret = {
|
|
1509
|
-
data: store._instanceCache.loadData(jsonApiDoc.data)
|
|
1510
|
-
};
|
|
1511
|
-
return;
|
|
1512
|
-
});
|
|
1513
|
-
return ret;
|
|
1514
|
-
}
|
|
1455
|
+
}), _class$1);
|
|
1515
1456
|
|
|
1516
1457
|
/**
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
* hook `instantiateRecord`, and the `recordDataFor`
|
|
1526
|
-
* method on the `CacheStoreWrapper`. It is not
|
|
1527
|
-
* directly instantiatable.
|
|
1528
|
-
*
|
|
1529
|
-
* It handles translating between cache versions when
|
|
1530
|
-
* necessary, for instance when a Store is configured
|
|
1531
|
-
* to use both a v1 and a v2 cache depending on some
|
|
1532
|
-
* heuristic.
|
|
1533
|
-
*
|
|
1534
|
-
* Starting with the v2 spec, the cache is designed such
|
|
1535
|
-
* that it must be implemented as a singleton. However,
|
|
1536
|
-
* because the v1 spec was not designed for this whenever
|
|
1537
|
-
* we encounter any v1 cache we must wrap all caches, even
|
|
1538
|
-
* singletons, in non-singleton managers to preserve v1
|
|
1539
|
-
* compatibility.
|
|
1540
|
-
*
|
|
1541
|
-
* To avoid this performance penalty being paid by all
|
|
1542
|
-
* applications, singleton behavior may be opted-in via
|
|
1543
|
-
* the configuration supplied to your Ember application
|
|
1544
|
-
* at build time. This effectively removes support for
|
|
1545
|
-
* v1 caches.
|
|
1546
|
-
*
|
|
1547
|
-
* ```js
|
|
1548
|
-
* let app = new EmberApp(defaults, {
|
|
1549
|
-
* emberData: {
|
|
1550
|
-
* useSingletonManager: true
|
|
1551
|
-
* },
|
|
1552
|
-
* });
|
|
1553
|
-
* ```
|
|
1554
|
-
*
|
|
1555
|
-
* @class CacheManager
|
|
1556
|
-
* @public
|
|
1557
|
-
*/
|
|
1558
|
-
var _store = /*#__PURE__*/_classPrivateFieldKey("store");
|
|
1559
|
-
var _cache = /*#__PURE__*/_classPrivateFieldKey("cache");
|
|
1560
|
-
var _identifier = /*#__PURE__*/_classPrivateFieldKey("identifier");
|
|
1561
|
-
var _isDeprecated = /*#__PURE__*/_classPrivateFieldKey("isDeprecated");
|
|
1562
|
-
class NonSingletonCacheManager {
|
|
1563
|
-
get managedVersion() {
|
|
1564
|
-
return _classPrivateFieldBase(this, _cache)[_cache].version || '1';
|
|
1565
|
-
}
|
|
1566
|
-
constructor(store, _cache2, identifier) {
|
|
1567
|
-
Object.defineProperty(this, _isDeprecated, {
|
|
1568
|
-
value: _isDeprecated2
|
|
1569
|
-
});
|
|
1570
|
-
this.version = '2';
|
|
1571
|
-
Object.defineProperty(this, _store, {
|
|
1572
|
-
writable: true,
|
|
1573
|
-
value: void 0
|
|
1574
|
-
});
|
|
1575
|
-
Object.defineProperty(this, _cache, {
|
|
1576
|
-
writable: true,
|
|
1577
|
-
value: void 0
|
|
1578
|
-
});
|
|
1579
|
-
Object.defineProperty(this, _identifier, {
|
|
1580
|
-
writable: true,
|
|
1581
|
-
value: void 0
|
|
1582
|
-
});
|
|
1583
|
-
_classPrivateFieldBase(this, _store)[_store] = store;
|
|
1584
|
-
_classPrivateFieldBase(this, _cache)[_cache] = _cache2;
|
|
1585
|
-
_classPrivateFieldBase(this, _identifier)[_identifier] = identifier;
|
|
1586
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](_cache2)) {
|
|
1587
|
-
deprecate(`This RecordData uses the deprecated V1 RecordData Spec. Upgrade to V2 to maintain compatibility.`, false, {
|
|
1588
|
-
id: 'ember-data:deprecate-v1-cache',
|
|
1589
|
-
until: '5.0',
|
|
1590
|
-
since: {
|
|
1591
|
-
available: '4.7',
|
|
1592
|
-
enabled: '4.7'
|
|
1593
|
-
},
|
|
1594
|
-
for: 'ember-data'
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1458
|
+
@module @ember-data/store
|
|
1459
|
+
*/
|
|
1460
|
+
|
|
1461
|
+
class CacheStoreWrapper {
|
|
1462
|
+
constructor(_store) {
|
|
1463
|
+
this._store = _store;
|
|
1464
|
+
this._willNotify = false;
|
|
1465
|
+
this._pendingNotifies = new Map();
|
|
1597
1466
|
}
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
/**
|
|
1601
|
-
* Cache the response to a request
|
|
1602
|
-
*
|
|
1603
|
-
* Unlike `store.push` which has UPSERT
|
|
1604
|
-
* semantics, `put` has `replace` semantics similar to
|
|
1605
|
-
* the `http` method `PUT`
|
|
1606
|
-
*
|
|
1607
|
-
* the individually cacheabl
|
|
1608
|
-
* e resource data it may contain
|
|
1609
|
-
* should upsert, but the document data surrounding it should
|
|
1610
|
-
* fully replace any existing information
|
|
1611
|
-
*
|
|
1612
|
-
* Note that in order to support inserting arbitrary data
|
|
1613
|
-
* to the cache that did not originate from a request `put`
|
|
1614
|
-
* should expect to sometimes encounter a document with only
|
|
1615
|
-
* a `content` member and therefor must not assume the existence
|
|
1616
|
-
* of `request` and `response` on the document.
|
|
1617
|
-
*
|
|
1618
|
-
* @method put
|
|
1619
|
-
* @param {StructuredDocument} doc
|
|
1620
|
-
* @returns {ResourceDocument}
|
|
1621
|
-
* @public
|
|
1622
|
-
*/
|
|
1623
|
-
put(doc) {
|
|
1624
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1625
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1626
|
-
if (doc instanceof Error) {
|
|
1627
|
-
// in legacy we don't know how to handle this
|
|
1628
|
-
throw doc;
|
|
1629
|
-
}
|
|
1630
|
-
return legacyCachePut(_classPrivateFieldBase(this, _store)[_store], doc);
|
|
1631
|
-
}
|
|
1632
|
-
return cache.put(doc);
|
|
1467
|
+
get identifierCache() {
|
|
1468
|
+
return this._store.identifierCache;
|
|
1633
1469
|
}
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
* @public
|
|
1643
|
-
* @param op the operation to perform
|
|
1644
|
-
* @returns {void}
|
|
1645
|
-
*/
|
|
1646
|
-
patch(op) {
|
|
1647
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1648
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1470
|
+
_scheduleNotification(identifier, key) {
|
|
1471
|
+
let pending = this._pendingNotifies.get(identifier);
|
|
1472
|
+
if (!pending) {
|
|
1473
|
+
pending = new Set();
|
|
1474
|
+
this._pendingNotifies.set(identifier, pending);
|
|
1475
|
+
}
|
|
1476
|
+
pending.add(key);
|
|
1477
|
+
if (this._willNotify === true) {
|
|
1649
1478
|
return;
|
|
1650
1479
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
* on relationships only.
|
|
1657
|
-
*
|
|
1658
|
-
* @method mutate
|
|
1659
|
-
* @public
|
|
1660
|
-
* @param mutation
|
|
1661
|
-
*/
|
|
1662
|
-
// isResource is only needed for interop with v1 cache
|
|
1663
|
-
mutate(mutation, isResource) {
|
|
1664
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1665
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1666
|
-
const instanceCache = _classPrivateFieldBase(this, _store)[_store]._instanceCache;
|
|
1667
|
-
switch (mutation.op) {
|
|
1668
|
-
case 'addToRelatedRecords':
|
|
1669
|
-
cache.addToHasMany(mutation.field, mutation.value.map(i => instanceCache.getResourceCache(i)), mutation.index);
|
|
1670
|
-
return;
|
|
1671
|
-
case 'removeFromRelatedRecords':
|
|
1672
|
-
cache.removeFromHasMany(mutation.field, mutation.value.map(i => instanceCache.getResourceCache(i)));
|
|
1673
|
-
return;
|
|
1674
|
-
case 'replaceRelatedRecords':
|
|
1675
|
-
cache.setDirtyHasMany(mutation.field, mutation.value.map(i => instanceCache.getResourceCache(i)));
|
|
1676
|
-
return;
|
|
1677
|
-
case 'replaceRelatedRecord':
|
|
1678
|
-
if (isResource) {
|
|
1679
|
-
cache.setDirtyBelongsTo(mutation.field, mutation.value ? instanceCache.getResourceCache(mutation.value) : null);
|
|
1680
|
-
return;
|
|
1681
|
-
}
|
|
1682
|
-
cache.removeFromHasMany(mutation.field, [instanceCache.getResourceCache(mutation.prior)]);
|
|
1683
|
-
cache.addToHasMany(mutation.field, [instanceCache.getResourceCache(mutation.value)], mutation.index);
|
|
1684
|
-
return;
|
|
1685
|
-
case 'sortRelatedRecords':
|
|
1686
|
-
return;
|
|
1687
|
-
default:
|
|
1688
|
-
return;
|
|
1689
|
-
}
|
|
1480
|
+
this._willNotify = true;
|
|
1481
|
+
// it's possible a cache adhoc notifies us,
|
|
1482
|
+
// in which case we sync flush
|
|
1483
|
+
if (this._store._cbs) {
|
|
1484
|
+
this._store._schedule('notify', () => this._flushNotifications());
|
|
1690
1485
|
} else {
|
|
1691
|
-
|
|
1486
|
+
this._flushNotifications();
|
|
1692
1487
|
}
|
|
1693
1488
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
*
|
|
1698
|
-
* In development, if the return value
|
|
1699
|
-
* is JSON the return value
|
|
1700
|
-
* will be deep-cloned and deep-frozen
|
|
1701
|
-
* to prevent mutation thereby enforcing cache
|
|
1702
|
-
* Immutability.
|
|
1703
|
-
*
|
|
1704
|
-
* This form of peek is useful for implementations
|
|
1705
|
-
* that want to feed raw-data from cache to the UI
|
|
1706
|
-
* or which want to interact with a blob of data
|
|
1707
|
-
* directly from the presentation cache.
|
|
1708
|
-
*
|
|
1709
|
-
* An implementation might want to do this because
|
|
1710
|
-
* de-referencing records which read from their own
|
|
1711
|
-
* blob is generally safer because the record does
|
|
1712
|
-
* not require retainining connections to the Store
|
|
1713
|
-
* and Cache to present data on a per-field basis.
|
|
1714
|
-
*
|
|
1715
|
-
* This generally takes the place of `getAttr` as
|
|
1716
|
-
* an API and may even take the place of `getRelationship`
|
|
1717
|
-
* depending on implementation specifics, though this
|
|
1718
|
-
* latter usage is less recommended due to the advantages
|
|
1719
|
-
* of the Graph handling necessary entanglements and
|
|
1720
|
-
* notifications for relational data.
|
|
1721
|
-
*
|
|
1722
|
-
* @method peek
|
|
1723
|
-
* @public
|
|
1724
|
-
* @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
|
|
1725
|
-
* @returns {ResourceDocument | ResourceBlob | null} the known resource data
|
|
1726
|
-
*/
|
|
1727
|
-
|
|
1728
|
-
peek(identifier) {
|
|
1729
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1730
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1731
|
-
throw new Error(`Expected cache to implement peek`);
|
|
1489
|
+
_flushNotifications() {
|
|
1490
|
+
if (this._willNotify === false) {
|
|
1491
|
+
return;
|
|
1732
1492
|
}
|
|
1733
|
-
|
|
1493
|
+
let pending = this._pendingNotifies;
|
|
1494
|
+
this._pendingNotifies = new Map();
|
|
1495
|
+
this._willNotify = false;
|
|
1496
|
+
pending.forEach((set, identifier) => {
|
|
1497
|
+
set.forEach(key => {
|
|
1498
|
+
this._store.notifications.notify(identifier, 'relationships', key);
|
|
1499
|
+
});
|
|
1500
|
+
});
|
|
1734
1501
|
}
|
|
1502
|
+
notifyChange(identifier, namespace, key) {
|
|
1503
|
+
assert(`Expected a stable identifier`, isStableIdentifier(identifier) || isDocumentIdentifier(identifier));
|
|
1735
1504
|
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
* @method peekRequest
|
|
1741
|
-
* @param {StableDocumentIdentifier}
|
|
1742
|
-
* @returns {StableDocumentIdentifier | null}
|
|
1743
|
-
* @public
|
|
1744
|
-
*/
|
|
1745
|
-
peekRequest(identifier) {
|
|
1746
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1747
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1748
|
-
throw new Error(`Expected cache to implement peekRequest`);
|
|
1505
|
+
// TODO do we still get value from this?
|
|
1506
|
+
if (namespace === 'relationships' && key) {
|
|
1507
|
+
this._scheduleNotification(identifier, key);
|
|
1508
|
+
return;
|
|
1749
1509
|
}
|
|
1750
|
-
return cache.peekRequest(identifier);
|
|
1751
|
-
}
|
|
1752
1510
|
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
}
|
|
1771
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1772
|
-
return cache.pushData(data, hasRecord);
|
|
1773
|
-
}
|
|
1774
|
-
return cache.upsert(identifier, data, hasRecord);
|
|
1511
|
+
// @ts-expect-error
|
|
1512
|
+
this._store.notifications.notify(identifier, namespace, key);
|
|
1513
|
+
}
|
|
1514
|
+
getSchemaDefinitionService() {
|
|
1515
|
+
return this._store.getSchemaDefinitionService();
|
|
1516
|
+
}
|
|
1517
|
+
setRecordId(identifier, id) {
|
|
1518
|
+
assert(`Expected a stable identifier`, isStableIdentifier(identifier));
|
|
1519
|
+
this._store._instanceCache.setRecordId(identifier, id);
|
|
1520
|
+
}
|
|
1521
|
+
hasRecord(identifier) {
|
|
1522
|
+
return Boolean(this._store._instanceCache.peek(identifier));
|
|
1523
|
+
}
|
|
1524
|
+
disconnectRecord(identifier) {
|
|
1525
|
+
assert(`Expected a stable identifier`, isStableIdentifier(identifier));
|
|
1526
|
+
this._store._instanceCache.disconnect(identifier);
|
|
1527
|
+
this._pendingNotifies.delete(identifier);
|
|
1775
1528
|
}
|
|
1529
|
+
}
|
|
1530
|
+
let _peekGraph;
|
|
1531
|
+
if (macroCondition(getOwnConfig().packages.HAS_GRAPH_PACKAGE)) {
|
|
1532
|
+
let __peekGraph;
|
|
1533
|
+
_peekGraph = wrapper => {
|
|
1534
|
+
let a = importSync('@ember-data/graph/-private').peekGraph;
|
|
1535
|
+
__peekGraph = __peekGraph || a;
|
|
1536
|
+
return __peekGraph(wrapper);
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1776
1539
|
|
|
1777
|
-
|
|
1778
|
-
|
|
1540
|
+
/**
|
|
1541
|
+
@module @ember-data/store
|
|
1542
|
+
*/
|
|
1779
1543
|
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
* preferring instead to fork at the Store level, which will
|
|
1785
|
-
* utilize this method to fork the cache.
|
|
1786
|
-
*
|
|
1787
|
-
* @method fork
|
|
1788
|
-
* @public
|
|
1789
|
-
* @returns Promise<Cache>
|
|
1790
|
-
*/
|
|
1791
|
-
fork() {
|
|
1792
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1793
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1794
|
-
throw new Error(`Expected cache to implement fork`);
|
|
1795
|
-
}
|
|
1796
|
-
return cache.fork();
|
|
1797
|
-
}
|
|
1544
|
+
const RecordCache = new Map();
|
|
1545
|
+
function peekRecordIdentifier(record) {
|
|
1546
|
+
return RecordCache.get(record);
|
|
1547
|
+
}
|
|
1798
1548
|
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1549
|
+
/**
|
|
1550
|
+
Retrieves the unique referentially-stable [RecordIdentifier](/ember-data/release/classes/StableRecordIdentifier)
|
|
1551
|
+
assigned to the given record instance.
|
|
1552
|
+
```js
|
|
1553
|
+
import { recordIdentifierFor } from "@ember-data/store";
|
|
1554
|
+
// ... gain access to a record, for instance with peekRecord or findRecord
|
|
1555
|
+
const record = store.peekRecord("user", "1");
|
|
1556
|
+
// get the identifier for the record (see docs for StableRecordIdentifier)
|
|
1557
|
+
const identifier = recordIdentifierFor(record);
|
|
1558
|
+
// access the identifier's properties.
|
|
1559
|
+
const { id, type, lid } = identifier;
|
|
1560
|
+
```
|
|
1561
|
+
@method recordIdentifierFor
|
|
1562
|
+
@public
|
|
1563
|
+
@static
|
|
1564
|
+
@for @ember-data/store
|
|
1565
|
+
@param {Object} record a record instance previously obstained from the store.
|
|
1566
|
+
@returns {StableRecordIdentifier}
|
|
1567
|
+
*/
|
|
1568
|
+
function recordIdentifierFor(record) {
|
|
1569
|
+
assert(`${String(record)} is not a record instantiated by @ember-data/store`, RecordCache.has(record));
|
|
1570
|
+
return RecordCache.get(record);
|
|
1571
|
+
}
|
|
1572
|
+
function setRecordIdentifier(record, identifier) {
|
|
1573
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
1574
|
+
if (RecordCache.has(record) && RecordCache.get(record) !== identifier) {
|
|
1575
|
+
throw new Error(`${String(record)} was already assigned an identifier`);
|
|
1815
1576
|
}
|
|
1816
|
-
return cache.merge(updates);
|
|
1817
1577
|
}
|
|
1818
1578
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
*
|
|
1827
|
-
* A `Change` is described by an object containing up to
|
|
1828
|
-
* three properties: (1) the `identifier` of the entity that
|
|
1829
|
-
* changed; (2) the `op` code of that change being one of
|
|
1830
|
-
* `upsert` or `remove`, and if the op is `upsert` a `patch`
|
|
1831
|
-
* containing the data to merge into the cache for the given
|
|
1832
|
-
* entity.
|
|
1833
|
-
*
|
|
1834
|
-
* This `patch` is opaque to the Store but should be understood
|
|
1835
|
-
* by the Cache and may expect to be utilized by an Adapter
|
|
1836
|
-
* when generating data during a `save` operation.
|
|
1837
|
-
*
|
|
1838
|
-
* It is generally recommended that the `patch` contain only
|
|
1839
|
-
* the updated state, ignoring fields that are unchanged
|
|
1840
|
-
*
|
|
1841
|
-
* ```ts
|
|
1842
|
-
* interface Change {
|
|
1843
|
-
* identifier: StableRecordIdentifier | StableDocumentIdentifier;
|
|
1844
|
-
* op: 'upsert' | 'remove';
|
|
1845
|
-
* patch?: unknown;
|
|
1846
|
-
* }
|
|
1847
|
-
* ```
|
|
1848
|
-
*
|
|
1849
|
-
* @method diff
|
|
1850
|
-
* @public
|
|
1851
|
-
*/
|
|
1852
|
-
diff() {
|
|
1853
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1854
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1855
|
-
throw new Error(`Expected cache to implement diff`);
|
|
1856
|
-
}
|
|
1857
|
-
return cache.diff();
|
|
1858
|
-
}
|
|
1579
|
+
/*
|
|
1580
|
+
It would be nice to do a reverse check here that an identifier has not
|
|
1581
|
+
previously been assigned a record; however, unload + rematerialization
|
|
1582
|
+
prevents us from having a great way of doing so when CustomRecordClasses
|
|
1583
|
+
don't necessarily give us access to a `isDestroyed` for dematerialized
|
|
1584
|
+
instance.
|
|
1585
|
+
*/
|
|
1859
1586
|
|
|
1860
|
-
|
|
1861
|
-
|
|
1587
|
+
RecordCache.set(record, identifier);
|
|
1588
|
+
}
|
|
1589
|
+
const StoreMap = new Map();
|
|
1590
|
+
function storeFor(record) {
|
|
1591
|
+
const store = StoreMap.get(record);
|
|
1592
|
+
assert(`A record in a disconnected state cannot utilize the store. This typically means the record has been destroyed, most commonly by unloading it.`, store);
|
|
1593
|
+
return store;
|
|
1594
|
+
}
|
|
1595
|
+
class InstanceCache {
|
|
1596
|
+
constructor(store) {
|
|
1597
|
+
this.__instances = {
|
|
1598
|
+
record: new Map(),
|
|
1599
|
+
reference: new WeakMap()
|
|
1600
|
+
};
|
|
1601
|
+
this.store = store;
|
|
1602
|
+
this._storeWrapper = new CacheStoreWrapper(this.store);
|
|
1603
|
+
store.identifierCache.__configureMerge((identifier, matchedIdentifier, resourceData) => {
|
|
1604
|
+
let keptIdentifier = identifier;
|
|
1605
|
+
if (identifier.id !== matchedIdentifier.id) {
|
|
1606
|
+
keptIdentifier = 'id' in resourceData && identifier.id === resourceData.id ? identifier : matchedIdentifier;
|
|
1607
|
+
} else if (identifier.type !== matchedIdentifier.type) {
|
|
1608
|
+
keptIdentifier = 'type' in resourceData && identifier.type === resourceData.type ? identifier : matchedIdentifier;
|
|
1609
|
+
}
|
|
1610
|
+
let staleIdentifier = identifier === keptIdentifier ? matchedIdentifier : identifier;
|
|
1862
1611
|
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
* via `cache.hydrate`.
|
|
1867
|
-
*
|
|
1868
|
-
* @method dump
|
|
1869
|
-
* @returns {Promise<ReadableStream>}
|
|
1870
|
-
* @public
|
|
1871
|
-
*/
|
|
1872
|
-
dump() {
|
|
1873
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1874
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1875
|
-
throw new Error(`Expected cache to implement dump`);
|
|
1876
|
-
}
|
|
1877
|
-
return cache.dump();
|
|
1878
|
-
}
|
|
1612
|
+
// check for duplicate entities
|
|
1613
|
+
let keptHasRecord = this.__instances.record.has(keptIdentifier);
|
|
1614
|
+
let staleHasRecord = this.__instances.record.has(staleIdentifier);
|
|
1879
1615
|
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
hydrate(stream) {
|
|
1898
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1899
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1900
|
-
throw new Error(`Expected cache to implement hydrate`);
|
|
1901
|
-
}
|
|
1902
|
-
return cache.hydrate(stream);
|
|
1903
|
-
}
|
|
1616
|
+
// we cannot merge entities when both have records
|
|
1617
|
+
// (this may not be strictly true, we could probably swap the cache data the record points at)
|
|
1618
|
+
if (keptHasRecord && staleHasRecord) {
|
|
1619
|
+
// TODO we probably don't need to throw these errors anymore
|
|
1620
|
+
// we can probably just "swap" what data source the abandoned
|
|
1621
|
+
// record points at so long as
|
|
1622
|
+
// it itself is not retained by the store in any way.
|
|
1623
|
+
if ('id' in resourceData) {
|
|
1624
|
+
throw new Error(`Failed to update the 'id' for the RecordIdentifier '${identifier.type}:${String(identifier.id)} (${identifier.lid})' to '${String(resourceData.id)}', because that id is already in use by '${matchedIdentifier.type}:${String(matchedIdentifier.id)} (${matchedIdentifier.lid})'`);
|
|
1625
|
+
}
|
|
1626
|
+
assert(`Failed to update the RecordIdentifier '${identifier.type}:${String(identifier.id)} (${identifier.lid})' to merge with the detected duplicate identifier '${matchedIdentifier.type}:${String(matchedIdentifier.id)} (${String(matchedIdentifier.lid)})'`);
|
|
1627
|
+
}
|
|
1628
|
+
this.store.cache.patch({
|
|
1629
|
+
op: 'mergeIdentifiers',
|
|
1630
|
+
record: staleIdentifier,
|
|
1631
|
+
value: keptIdentifier
|
|
1632
|
+
});
|
|
1904
1633
|
|
|
1905
|
-
|
|
1906
|
-
|
|
1634
|
+
/*
|
|
1635
|
+
TODO @runspired consider adding this to make polymorphism even nicer
|
|
1636
|
+
if (HAS_GRAPH_PACKAGE) {
|
|
1637
|
+
if (identifier.type !== matchedIdentifier.type) {
|
|
1638
|
+
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
1639
|
+
graphFor(this).registerPolymorphicType(identifier.type, matchedIdentifier.type);
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
*/
|
|
1907
1643
|
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
* DEPRECATED Caches should not be assumed to be 1:1 with resources
|
|
1912
|
-
*
|
|
1913
|
-
* @method getResourceIdentifier
|
|
1914
|
-
* @public
|
|
1915
|
-
* @deprecated
|
|
1916
|
-
*/
|
|
1917
|
-
getResourceIdentifier() {
|
|
1918
|
-
return _classPrivateFieldBase(this, _identifier)[_identifier];
|
|
1644
|
+
this.unloadRecord(staleIdentifier);
|
|
1645
|
+
return keptIdentifier;
|
|
1646
|
+
});
|
|
1919
1647
|
}
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
* Push resource data from a remote source into the cache for this identifier
|
|
1923
|
-
*
|
|
1924
|
-
* DEPRECATED Use upsert. Caches should not be assumed to be 1:1 with resources
|
|
1925
|
-
*
|
|
1926
|
-
* @method pushData
|
|
1927
|
-
* @param data
|
|
1928
|
-
* @param hasRecord
|
|
1929
|
-
* @returns {void | string[]} if `hasRecord` is true then calculated key changes should be returned
|
|
1930
|
-
* @public
|
|
1931
|
-
* @deprecated
|
|
1932
|
-
*/
|
|
1933
|
-
pushData(data, hasRecord) {
|
|
1934
|
-
return this.upsert(_classPrivateFieldBase(this, _identifier)[_identifier], data, hasRecord);
|
|
1648
|
+
peek(identifier) {
|
|
1649
|
+
return this.__instances.record.get(identifier);
|
|
1935
1650
|
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
clientDidCreate(identifier, options) {
|
|
1952
|
-
// called by something V1
|
|
1953
|
-
if (!isStableIdentifier(identifier)) {
|
|
1954
|
-
options = identifier;
|
|
1955
|
-
identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
|
|
1956
|
-
}
|
|
1957
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1958
|
-
|
|
1959
|
-
// TODO deprecate return value
|
|
1960
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1961
|
-
cache.clientDidCreate();
|
|
1962
|
-
// if a V2 is calling a V1 we need to call both methods
|
|
1963
|
-
return cache._initRecordCreateOptions(options);
|
|
1964
|
-
} else {
|
|
1965
|
-
return cache.clientDidCreate(identifier, options);
|
|
1651
|
+
getRecord(identifier, properties) {
|
|
1652
|
+
let record = this.__instances.record.get(identifier);
|
|
1653
|
+
if (!record) {
|
|
1654
|
+
assert(`Cannot create a new record instance while the store is being destroyed`, !this.store.isDestroying && !this.store.isDestroyed);
|
|
1655
|
+
const cache = this.store.cache;
|
|
1656
|
+
setCacheFor(identifier, cache);
|
|
1657
|
+
record = this.store.instantiateRecord(identifier, properties || {});
|
|
1658
|
+
setRecordIdentifier(record, identifier);
|
|
1659
|
+
setCacheFor(record, cache);
|
|
1660
|
+
StoreMap.set(record, this.store);
|
|
1661
|
+
this.__instances.record.set(identifier, record);
|
|
1662
|
+
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
1663
|
+
// eslint-disable-next-line no-console
|
|
1664
|
+
console.log(`InstanceCache: created Record for ${String(identifier)}`, properties);
|
|
1665
|
+
}
|
|
1966
1666
|
}
|
|
1667
|
+
return record;
|
|
1967
1668
|
}
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
*
|
|
1975
|
-
* @method clientDidCreate
|
|
1976
|
-
* @public
|
|
1977
|
-
* @deprecated
|
|
1978
|
-
* @param options
|
|
1979
|
-
*/
|
|
1980
|
-
_initRecordCreateOptions(options) {
|
|
1981
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
1982
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
1983
|
-
return cache._initRecordCreateOptions(options);
|
|
1669
|
+
getReference(identifier) {
|
|
1670
|
+
let cache = this.__instances.reference;
|
|
1671
|
+
let reference = cache.get(identifier);
|
|
1672
|
+
if (!reference) {
|
|
1673
|
+
reference = new RecordReference(this.store, identifier);
|
|
1674
|
+
cache.set(identifier, reference);
|
|
1984
1675
|
}
|
|
1676
|
+
return reference;
|
|
1985
1677
|
}
|
|
1678
|
+
recordIsLoaded(identifier, filterDeleted = false) {
|
|
1679
|
+
const cache = this.cache;
|
|
1680
|
+
if (!cache) {
|
|
1681
|
+
return false;
|
|
1682
|
+
}
|
|
1683
|
+
const isNew = cache.isNew(identifier);
|
|
1684
|
+
const isEmpty = cache.isEmpty(identifier);
|
|
1986
1685
|
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
*
|
|
1991
|
-
* @method willCommit
|
|
1992
|
-
* @public
|
|
1993
|
-
* @param identifier
|
|
1994
|
-
*/
|
|
1995
|
-
willCommit(identifier) {
|
|
1996
|
-
_classPrivateFieldBase(this, _cache)[_cache].willCommit(identifier || _classPrivateFieldBase(this, _identifier)[_identifier]);
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
|
-
/**
|
|
2000
|
-
* [LIFECYCLE] Signals to the cache that a resource
|
|
2001
|
-
* was successfully updated as part of a save transaction.
|
|
2002
|
-
*
|
|
2003
|
-
* @method didCommit
|
|
2004
|
-
* @public
|
|
2005
|
-
* @param identifier
|
|
2006
|
-
* @param data
|
|
2007
|
-
*/
|
|
2008
|
-
didCommit(identifier, data) {
|
|
2009
|
-
// called by something V1
|
|
2010
|
-
if (!isStableIdentifier(identifier)) {
|
|
2011
|
-
data = identifier;
|
|
2012
|
-
identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
|
|
1686
|
+
// if we are new we must consider ourselves loaded
|
|
1687
|
+
if (isNew) {
|
|
1688
|
+
return !cache.isDeleted(identifier);
|
|
2013
1689
|
}
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
}
|
|
1690
|
+
// even if we have a past request, if we are now empty we are not loaded
|
|
1691
|
+
// typically this is true after an unloadRecord call
|
|
2017
1692
|
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
* @public
|
|
2024
|
-
* @param identifier
|
|
2025
|
-
* @param errors
|
|
2026
|
-
*/
|
|
2027
|
-
commitWasRejected(identifier, errors) {
|
|
2028
|
-
_classPrivateFieldBase(this, _cache)[_cache].commitWasRejected(identifier || _classPrivateFieldBase(this, _identifier)[_identifier], errors);
|
|
1693
|
+
// if we are not empty, not new && we have a fulfilled request then we are loaded
|
|
1694
|
+
// we should consider allowing for something to be loaded that is simply "not empty".
|
|
1695
|
+
// which is how RecordState currently handles this case; however, RecordState is buggy
|
|
1696
|
+
// in that it does not account for unloading.
|
|
1697
|
+
return filterDeleted && cache.isDeletionCommitted(identifier) ? false : !isEmpty;
|
|
2029
1698
|
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
1699
|
+
disconnect(identifier) {
|
|
1700
|
+
const record = this.__instances.record.get(identifier);
|
|
1701
|
+
assert('Cannot destroy record while it is still materialized', !record || record.isDestroyed || record.isDestroying);
|
|
1702
|
+
if (macroCondition(getOwnConfig().packages.HAS_GRAPH_PACKAGE)) {
|
|
1703
|
+
let graph = _peekGraph(this.store);
|
|
1704
|
+
if (graph) {
|
|
1705
|
+
graph.remove(identifier);
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
this.store.identifierCache.forgetRecordIdentifier(identifier);
|
|
1709
|
+
removeRecordDataFor(identifier);
|
|
1710
|
+
this.store._requestCache._clearEntries(identifier);
|
|
1711
|
+
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
1712
|
+
// eslint-disable-next-line no-console
|
|
1713
|
+
console.log(`InstanceCache: disconnected ${String(identifier)}`);
|
|
2045
1714
|
}
|
|
2046
1715
|
}
|
|
1716
|
+
unloadRecord(identifier) {
|
|
1717
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
1718
|
+
const requests = this.store.getRequestStateService().getPendingRequestsForRecord(identifier);
|
|
1719
|
+
if (requests.some(req => {
|
|
1720
|
+
return req.type === 'mutation';
|
|
1721
|
+
})) {
|
|
1722
|
+
assert(`You can only unload a record which is not inFlight. '${String(identifier)}'`);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
1726
|
+
// eslint-disable-next-line no-console
|
|
1727
|
+
console.groupCollapsed(`InstanceCache: unloading record for ${String(identifier)}`);
|
|
1728
|
+
}
|
|
2047
1729
|
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
1730
|
+
// TODO is this join still necessary?
|
|
1731
|
+
this.store._join(() => {
|
|
1732
|
+
const record = this.__instances.record.get(identifier);
|
|
1733
|
+
const cache = this.cache;
|
|
1734
|
+
if (record) {
|
|
1735
|
+
this.store.teardownRecord(record);
|
|
1736
|
+
this.__instances.record.delete(identifier);
|
|
1737
|
+
StoreMap.delete(record);
|
|
1738
|
+
RecordCache.delete(record);
|
|
1739
|
+
removeRecordDataFor(record);
|
|
1740
|
+
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
1741
|
+
// eslint-disable-next-line no-console
|
|
1742
|
+
console.log(`InstanceCache: destroyed record for ${String(identifier)}`);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
if (cache) {
|
|
1746
|
+
cache.unloadRecord(identifier);
|
|
1747
|
+
removeRecordDataFor(identifier);
|
|
1748
|
+
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
1749
|
+
// eslint-disable-next-line no-console
|
|
1750
|
+
console.log(`InstanceCache: destroyed cache for ${String(identifier)}`);
|
|
1751
|
+
}
|
|
1752
|
+
} else {
|
|
1753
|
+
this.disconnect(identifier);
|
|
1754
|
+
}
|
|
1755
|
+
this.store._requestCache._clearEntries(identifier);
|
|
1756
|
+
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
1757
|
+
// eslint-disable-next-line no-console
|
|
1758
|
+
console.log(`InstanceCache: unloaded RecordData for ${String(identifier)}`);
|
|
1759
|
+
// eslint-disable-next-line no-console
|
|
1760
|
+
console.groupEnd();
|
|
1761
|
+
}
|
|
1762
|
+
});
|
|
1763
|
+
}
|
|
1764
|
+
clear(type) {
|
|
1765
|
+
const cache = this.store.identifierCache._cache;
|
|
1766
|
+
if (type === undefined) {
|
|
1767
|
+
// it would be cool if we could just de-ref cache here
|
|
1768
|
+
// but probably would require WeakRef models to do so.
|
|
1769
|
+
cache.lids.forEach(identifier => {
|
|
1770
|
+
this.unloadRecord(identifier);
|
|
1771
|
+
});
|
|
1772
|
+
} else {
|
|
1773
|
+
const typeCache = cache.types;
|
|
1774
|
+
let identifiers = typeCache[type]?.lid;
|
|
1775
|
+
if (identifiers) {
|
|
1776
|
+
identifiers.forEach(identifier => {
|
|
1777
|
+
// if (rds.has(identifier)) {
|
|
1778
|
+
this.unloadRecord(identifier);
|
|
1779
|
+
// }
|
|
1780
|
+
// TODO we don't remove the identifier, should we?
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
2065
1783
|
}
|
|
2066
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2067
|
-
return _classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.getAttr(propertyName) : cache.getAttr(identifier, propertyName);
|
|
2068
1784
|
}
|
|
2069
1785
|
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
* @param value
|
|
2078
|
-
*/
|
|
2079
|
-
setAttr(identifier, propertyName, value) {
|
|
2080
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2081
|
-
_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.setDirtyAttribute(propertyName, value) : cache.setAttr(identifier, propertyName, value);
|
|
2082
|
-
}
|
|
1786
|
+
// TODO this should move into something coordinating operations
|
|
1787
|
+
setRecordId(identifier, id) {
|
|
1788
|
+
const {
|
|
1789
|
+
type,
|
|
1790
|
+
lid
|
|
1791
|
+
} = identifier;
|
|
1792
|
+
let oldId = identifier.id;
|
|
2083
1793
|
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
*
|
|
2087
|
-
* DEPRECATED use setAttr
|
|
2088
|
-
*
|
|
2089
|
-
* @method setDirtyAttribute
|
|
2090
|
-
* @public
|
|
2091
|
-
* @deprecated
|
|
2092
|
-
* @param identifier
|
|
2093
|
-
* @param propertyName
|
|
2094
|
-
* @param value
|
|
2095
|
-
*/
|
|
2096
|
-
setDirtyAttribute(propertyName, value) {
|
|
2097
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2098
|
-
_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.setDirtyAttribute(propertyName, value) : cache.setAttr(_classPrivateFieldBase(this, _identifier)[_identifier], propertyName, value);
|
|
2099
|
-
}
|
|
1794
|
+
// ID absolutely can't be missing if the oldID is empty (missing Id in response for a new record)
|
|
1795
|
+
assert(`'${type}' was saved to the server, but the response does not have an id and your record does not either.`, !(id === null && oldId === null));
|
|
2100
1796
|
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
* DEPRECATED use changedAttrs
|
|
2105
|
-
*
|
|
2106
|
-
* @method changedAttributes
|
|
2107
|
-
* @public
|
|
2108
|
-
* @deprecated
|
|
2109
|
-
* @param identifier
|
|
2110
|
-
* @returns
|
|
2111
|
-
*/
|
|
2112
|
-
changedAttributes() {
|
|
2113
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2114
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
2115
|
-
return cache.changedAttributes();
|
|
2116
|
-
}
|
|
2117
|
-
return cache.changedAttrs(_classPrivateFieldBase(this, _identifier)[_identifier]);
|
|
2118
|
-
}
|
|
1797
|
+
// ID absolutely can't be different than oldID if oldID is not null
|
|
1798
|
+
// TODO this assertion and restriction may not strictly be needed in the identifiers world
|
|
1799
|
+
assert(`Cannot update the id for '${type}:${lid}' from '${String(oldId)}' to '${id}'.`, !(oldId !== null && id !== oldId));
|
|
2119
1800
|
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
1801
|
+
// ID can be null if oldID is not null (altered ID in response for a record)
|
|
1802
|
+
// however, this is more than likely a developer error.
|
|
1803
|
+
if (oldId !== null && id === null) {
|
|
1804
|
+
warn(`Your ${type} record was saved to the server, but the response does not have an id.`, !(oldId !== null && id === null));
|
|
1805
|
+
return;
|
|
1806
|
+
}
|
|
1807
|
+
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
1808
|
+
// eslint-disable-next-line no-console
|
|
1809
|
+
console.log(`InstanceCache: updating id to '${id}' for record ${String(identifier)}`);
|
|
1810
|
+
}
|
|
1811
|
+
let existingIdentifier = this.store.identifierCache.peekRecordIdentifier({
|
|
1812
|
+
type,
|
|
1813
|
+
id
|
|
1814
|
+
});
|
|
1815
|
+
assert(`'${type}' was saved to the server, but the response returned the new id '${id}', which has already been used with another record.'`, !existingIdentifier || existingIdentifier === identifier);
|
|
1816
|
+
if (identifier.id === null) {
|
|
1817
|
+
// TODO potentially this needs to handle merged result
|
|
1818
|
+
this.store.identifierCache.updateRecordIdentifier(identifier, {
|
|
1819
|
+
type,
|
|
1820
|
+
id
|
|
1821
|
+
});
|
|
2133
1822
|
}
|
|
2134
|
-
return cache.changedAttrs(identifier);
|
|
2135
|
-
}
|
|
2136
|
-
|
|
2137
|
-
/**
|
|
2138
|
-
* Query the cache for whether any mutated attributes exist
|
|
2139
|
-
*
|
|
2140
|
-
* DEPRECATED use hasChangedAttrs
|
|
2141
|
-
*
|
|
2142
|
-
* @method hasChangedAttributes
|
|
2143
|
-
* @public
|
|
2144
|
-
* @deprecated
|
|
2145
|
-
* @returns {boolean}
|
|
2146
|
-
*/
|
|
2147
|
-
hasChangedAttributes() {
|
|
2148
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2149
|
-
return _classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.hasChangedAttributes() : cache.hasChangedAttrs(_classPrivateFieldBase(this, _identifier)[_identifier]);
|
|
2150
|
-
}
|
|
2151
1823
|
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
* @method hasChangedAttrs
|
|
2156
|
-
* @public
|
|
2157
|
-
* @param identifier
|
|
2158
|
-
* @returns {boolean}
|
|
2159
|
-
*/
|
|
2160
|
-
hasChangedAttrs(identifier) {
|
|
2161
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2162
|
-
return _classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.hasChangedAttributes() : cache.hasChangedAttrs(identifier);
|
|
1824
|
+
// TODO update resource cache if needed ?
|
|
1825
|
+
// TODO handle consequences of identifier merge for notifications
|
|
1826
|
+
this.store.notifications.notify(identifier, 'identity');
|
|
2163
1827
|
}
|
|
1828
|
+
}
|
|
1829
|
+
function _resourceIsFullDeleted(identifier, cache) {
|
|
1830
|
+
return cache.isDeletionCommitted(identifier) || cache.isNew(identifier) && cache.isDeleted(identifier);
|
|
1831
|
+
}
|
|
1832
|
+
function resourceIsFullyDeleted(instanceCache, identifier) {
|
|
1833
|
+
const cache = instanceCache.cache;
|
|
1834
|
+
return !cache || _resourceIsFullDeleted(identifier, cache);
|
|
1835
|
+
}
|
|
2164
1836
|
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
* @deprecated
|
|
2173
|
-
* @returns
|
|
2174
|
-
*/
|
|
2175
|
-
rollbackAttributes() {
|
|
2176
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2177
|
-
return _classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.rollbackAttributes() : cache.rollbackAttrs(_classPrivateFieldBase(this, _identifier)[_identifier]);
|
|
2178
|
-
}
|
|
2179
|
-
|
|
2180
|
-
/**
|
|
2181
|
-
* Tell the cache to discard any uncommitted mutations to attributes
|
|
2182
|
-
*
|
|
2183
|
-
* @method rollbackAttrs
|
|
2184
|
-
* @public
|
|
2185
|
-
* @param identifier
|
|
2186
|
-
* @returns the names of attributes that were restored
|
|
2187
|
-
*/
|
|
2188
|
-
rollbackAttrs(identifier) {
|
|
2189
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2190
|
-
return _classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.rollbackAttributes() : cache.rollbackAttrs(identifier);
|
|
2191
|
-
}
|
|
1837
|
+
/*
|
|
1838
|
+
When a find request is triggered on the store, the user can optionally pass in
|
|
1839
|
+
attributes and relationships to be preloaded. These are meant to behave as if they
|
|
1840
|
+
came back from the server, except the user obtained them out of band and is informing
|
|
1841
|
+
the store of their existence. The most common use case is for supporting client side
|
|
1842
|
+
nested URLs, such as `/posts/1/comments/2` so the user can do
|
|
1843
|
+
`store.findRecord('comment', 2, { preload: { post: 1 } })` without having to fetch the post.
|
|
2192
1844
|
|
|
2193
|
-
|
|
2194
|
-
|
|
1845
|
+
Preloaded data can be attributes and relationships passed in either as IDs or as actual
|
|
1846
|
+
models.
|
|
1847
|
+
*/
|
|
2195
1848
|
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
//
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
let isBelongsTo = !isCollection;
|
|
2215
|
-
return isBelongsTo ? cache.getBelongsTo(propertyName) : cache.getHasMany(propertyName);
|
|
1849
|
+
function preloadData(store, identifier, preload) {
|
|
1850
|
+
let jsonPayload = {};
|
|
1851
|
+
//TODO(Igor) consider the polymorphic case
|
|
1852
|
+
const schemas = store.getSchemaDefinitionService();
|
|
1853
|
+
const relationships = schemas.relationshipsDefinitionFor(identifier);
|
|
1854
|
+
Object.keys(preload).forEach(key => {
|
|
1855
|
+
let preloadValue = preload[key];
|
|
1856
|
+
let relationshipMeta = relationships[key];
|
|
1857
|
+
if (relationshipMeta) {
|
|
1858
|
+
if (!jsonPayload.relationships) {
|
|
1859
|
+
jsonPayload.relationships = {};
|
|
1860
|
+
}
|
|
1861
|
+
jsonPayload.relationships[key] = preloadRelationship(relationshipMeta, preloadValue);
|
|
1862
|
+
} else {
|
|
1863
|
+
if (!jsonPayload.attributes) {
|
|
1864
|
+
jsonPayload.attributes = {};
|
|
1865
|
+
}
|
|
1866
|
+
jsonPayload.attributes[key] = preloadValue;
|
|
2216
1867
|
}
|
|
2217
|
-
|
|
1868
|
+
});
|
|
1869
|
+
const cache = store.cache;
|
|
1870
|
+
const hasRecord = Boolean(store._instanceCache.peek(identifier));
|
|
1871
|
+
cache.upsert(identifier, jsonPayload, hasRecord);
|
|
1872
|
+
}
|
|
1873
|
+
function preloadRelationship(schema, preloadValue) {
|
|
1874
|
+
const relatedType = schema.type;
|
|
1875
|
+
if (schema.kind === 'hasMany') {
|
|
1876
|
+
assert('You need to pass in an array to set a hasMany property on a record', Array.isArray(preloadValue));
|
|
1877
|
+
return {
|
|
1878
|
+
data: preloadValue.map(value => _convertPreloadRelationshipToJSON(value, relatedType))
|
|
1879
|
+
};
|
|
2218
1880
|
}
|
|
1881
|
+
assert('You should not pass in an array to set a belongsTo property on a record', !Array.isArray(preloadValue));
|
|
1882
|
+
return {
|
|
1883
|
+
data: preloadValue ? _convertPreloadRelationshipToJSON(preloadValue, relatedType) : null
|
|
1884
|
+
};
|
|
1885
|
+
}
|
|
2219
1886
|
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
1887
|
+
/*
|
|
1888
|
+
findRecord('user', '1', { preload: { friends: ['1'] }});
|
|
1889
|
+
findRecord('user', '1', { preload: { friends: [record] }});
|
|
1890
|
+
*/
|
|
1891
|
+
function _convertPreloadRelationshipToJSON(value, type) {
|
|
1892
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
1893
|
+
return {
|
|
1894
|
+
type,
|
|
1895
|
+
id: value
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
// TODO if not a record instance assert it's an identifier
|
|
1899
|
+
// and allow identifiers to be used
|
|
1900
|
+
return recordIdentifierFor(value);
|
|
1901
|
+
}
|
|
1902
|
+
function _clearCaches() {
|
|
1903
|
+
RecordCache.clear();
|
|
1904
|
+
StoreMap.clear();
|
|
1905
|
+
CacheForIdentifierCache.clear();
|
|
1906
|
+
}
|
|
1907
|
+
let _modelForMixin;
|
|
1908
|
+
if (macroCondition(getOwnConfig().packages.HAS_MODEL_PACKAGE)) {
|
|
1909
|
+
let _found;
|
|
1910
|
+
_modelForMixin = function () {
|
|
1911
|
+
if (!_found) {
|
|
1912
|
+
_found = importSync('@ember-data/model/-private')._modelForMixin;
|
|
2238
1913
|
}
|
|
1914
|
+
return _found(...arguments);
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
class DSModelSchemaDefinitionService {
|
|
1918
|
+
constructor(store) {
|
|
1919
|
+
this.store = store;
|
|
1920
|
+
this._relationshipsDefCache = Object.create(null);
|
|
1921
|
+
this._attributesDefCache = Object.create(null);
|
|
2239
1922
|
}
|
|
2240
1923
|
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
getHasMany(propertyName) {
|
|
2253
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2254
|
-
if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
|
|
2255
|
-
return cache.getHasMany(propertyName);
|
|
2256
|
-
} else {
|
|
2257
|
-
let identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
|
|
2258
|
-
return cache.getRelationship(identifier, propertyName);
|
|
1924
|
+
// Following the existing RD implementation
|
|
1925
|
+
attributesDefinitionFor(identifier) {
|
|
1926
|
+
let modelName, attributes;
|
|
1927
|
+
modelName = identifier.type;
|
|
1928
|
+
attributes = this._attributesDefCache[modelName];
|
|
1929
|
+
if (attributes === undefined) {
|
|
1930
|
+
let modelClass = this.store.modelFor(modelName);
|
|
1931
|
+
let attributeMap = modelClass.attributes;
|
|
1932
|
+
attributes = Object.create(null);
|
|
1933
|
+
attributeMap.forEach((meta, name) => attributes[name] = meta);
|
|
1934
|
+
this._attributesDefCache[modelName] = attributes;
|
|
2259
1935
|
}
|
|
1936
|
+
return attributes;
|
|
2260
1937
|
}
|
|
2261
1938
|
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
setDirtyBelongsTo(propertyName, value) {
|
|
2274
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2275
|
-
_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.setDirtyBelongsTo(propertyName, value) : cache.mutate({
|
|
2276
|
-
op: 'replaceRelatedRecord',
|
|
2277
|
-
record: _classPrivateFieldBase(this, _identifier)[_identifier],
|
|
2278
|
-
field: propertyName,
|
|
2279
|
-
value: value ? value.getResourceIdentifier() : null
|
|
2280
|
-
});
|
|
1939
|
+
// Following the existing RD implementation
|
|
1940
|
+
relationshipsDefinitionFor(identifier) {
|
|
1941
|
+
let modelName, relationships;
|
|
1942
|
+
modelName = identifier.type;
|
|
1943
|
+
relationships = this._relationshipsDefCache[modelName];
|
|
1944
|
+
if (relationships === undefined) {
|
|
1945
|
+
let modelClass = this.store.modelFor(modelName);
|
|
1946
|
+
relationships = modelClass.relationshipsObject || null;
|
|
1947
|
+
this._relationshipsDefCache[modelName] = relationships;
|
|
1948
|
+
}
|
|
1949
|
+
return relationships;
|
|
2281
1950
|
}
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
* where in the list to insert the records
|
|
2287
|
-
*
|
|
2288
|
-
* DEPRECATED use update
|
|
2289
|
-
*
|
|
2290
|
-
* @method addToHasMany
|
|
2291
|
-
* @deprecated
|
|
2292
|
-
* @public
|
|
2293
|
-
* @param propertyName
|
|
2294
|
-
* @param value
|
|
2295
|
-
* @param idx
|
|
2296
|
-
*/
|
|
2297
|
-
addToHasMany(propertyName, value, idx) {
|
|
2298
|
-
const identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
|
|
2299
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2300
|
-
_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.addToHasMany(propertyName, value, idx) : cache.mutate({
|
|
2301
|
-
op: 'addToRelatedRecords',
|
|
2302
|
-
field: propertyName,
|
|
2303
|
-
record: identifier,
|
|
2304
|
-
value: value.map(v => v.getResourceIdentifier())
|
|
2305
|
-
});
|
|
1951
|
+
doesTypeExist(modelName) {
|
|
1952
|
+
let normalizedModelName = normalizeModelName(modelName);
|
|
1953
|
+
let factory = getModelFactory(this.store, this.store._modelFactoryCache, normalizedModelName);
|
|
1954
|
+
return factory !== null;
|
|
2306
1955
|
}
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
1956
|
+
}
|
|
1957
|
+
function getModelFactory(store, cache, normalizedModelName) {
|
|
1958
|
+
let factory = cache[normalizedModelName];
|
|
1959
|
+
if (!factory) {
|
|
1960
|
+
let owner = getOwner(store);
|
|
1961
|
+
factory = owner.factoryFor(`model:${normalizedModelName}`);
|
|
1962
|
+
if (macroCondition(getOwnConfig().packages.HAS_MODEL_PACKAGE)) {
|
|
1963
|
+
if (!factory) {
|
|
1964
|
+
//Support looking up mixins as base types for polymorphic relationships
|
|
1965
|
+
factory = _modelForMixin(store, normalizedModelName);
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
if (!factory) {
|
|
1969
|
+
// we don't cache misses in case someone wants to register a missing model
|
|
1970
|
+
return null;
|
|
1971
|
+
}
|
|
1972
|
+
let klass = factory.class;
|
|
1973
|
+
if (klass.isModel) {
|
|
1974
|
+
let hasOwnModelNameSet = klass.modelName && Object.prototype.hasOwnProperty.call(klass, 'modelName');
|
|
1975
|
+
if (!hasOwnModelNameSet) {
|
|
1976
|
+
Object.defineProperty(klass, 'modelName', {
|
|
1977
|
+
value: normalizedModelName
|
|
1978
|
+
});
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
cache[normalizedModelName] = factory;
|
|
2328
1982
|
}
|
|
1983
|
+
return factory;
|
|
1984
|
+
}
|
|
2329
1985
|
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
* @param propertyName
|
|
2339
|
-
* @param value
|
|
2340
|
-
*/
|
|
2341
|
-
setDirtyHasMany(propertyName, value) {
|
|
2342
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2343
|
-
_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.setDirtyHasMany(propertyName, value) : cache.mutate({
|
|
2344
|
-
op: 'replaceRelatedRecords',
|
|
2345
|
-
record: _classPrivateFieldBase(this, _identifier)[_identifier],
|
|
2346
|
-
field: propertyName,
|
|
2347
|
-
value: value.map(rd => rd.getResourceIdentifier())
|
|
2348
|
-
});
|
|
1986
|
+
// if modelFor turns out to be a bottleneck we should replace with a Map
|
|
1987
|
+
// and clear it during store teardown.
|
|
1988
|
+
const AvailableShims = new WeakMap();
|
|
1989
|
+
function getShimClass(store, modelName) {
|
|
1990
|
+
let shims = AvailableShims.get(store);
|
|
1991
|
+
if (!shims) {
|
|
1992
|
+
shims = Object.create(null);
|
|
1993
|
+
AvailableShims.set(store, shims);
|
|
2349
1994
|
}
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
* @param isDeleted
|
|
2362
|
-
*/
|
|
2363
|
-
setIsDeleted(identifier, isDeleted) {
|
|
2364
|
-
if (!isStableIdentifier(identifier)) {
|
|
2365
|
-
isDeleted = identifier;
|
|
2366
|
-
identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
|
|
1995
|
+
let shim = shims[modelName];
|
|
1996
|
+
if (shim === undefined) {
|
|
1997
|
+
shim = shims[modelName] = new ShimModelClass(store, modelName);
|
|
1998
|
+
}
|
|
1999
|
+
return shim;
|
|
2000
|
+
}
|
|
2001
|
+
function mapFromHash(hash) {
|
|
2002
|
+
let map = new Map();
|
|
2003
|
+
for (let i in hash) {
|
|
2004
|
+
if (Object.prototype.hasOwnProperty.call(hash, i)) {
|
|
2005
|
+
map.set(i, hash[i]);
|
|
2367
2006
|
}
|
|
2368
|
-
const cache = _classPrivateFieldBase(this, _cache)[_cache];
|
|
2369
|
-
_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.setIsDeleted(isDeleted) : cache.setIsDeleted(identifier, isDeleted);
|
|
2370
2007
|
}
|
|
2008
|
+
return map;
|
|
2009
|
+
}
|
|
2371
2010
|
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2011
|
+
// Mimics the static apis of DSModel
|
|
2012
|
+
class ShimModelClass {
|
|
2013
|
+
constructor(store, modelName) {
|
|
2014
|
+
this.__store = store;
|
|
2015
|
+
this.modelName = modelName;
|
|
2016
|
+
}
|
|
2017
|
+
get fields() {
|
|
2018
|
+
let attrs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({
|
|
2019
|
+
type: this.modelName
|
|
2020
|
+
});
|
|
2021
|
+
let relationships = this.__store.getSchemaDefinitionService().relationshipsDefinitionFor({
|
|
2022
|
+
type: this.modelName
|
|
2023
|
+
});
|
|
2024
|
+
let fields = new Map();
|
|
2025
|
+
Object.keys(attrs).forEach(key => fields.set(key, 'attribute'));
|
|
2026
|
+
Object.keys(relationships).forEach(key => fields.set(key, relationships[key].kind));
|
|
2027
|
+
return fields;
|
|
2028
|
+
}
|
|
2029
|
+
get attributes() {
|
|
2030
|
+
let attrs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({
|
|
2031
|
+
type: this.modelName
|
|
2032
|
+
});
|
|
2033
|
+
return mapFromHash(attrs);
|
|
2034
|
+
}
|
|
2035
|
+
get relationshipsByName() {
|
|
2036
|
+
let relationships = this.__store.getSchemaDefinitionService().relationshipsDefinitionFor({
|
|
2037
|
+
type: this.modelName
|
|
2038
|
+
});
|
|
2039
|
+
return mapFromHash(relationships);
|
|
2040
|
+
}
|
|
2041
|
+
eachAttribute(callback, binding) {
|
|
2042
|
+
let attrDefs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({
|
|
2043
|
+
type: this.modelName
|
|
2044
|
+
});
|
|
2045
|
+
Object.keys(attrDefs).forEach(key => {
|
|
2046
|
+
callback.call(binding, key, attrDefs[key]);
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
eachRelationship(callback, binding) {
|
|
2050
|
+
let relationshipDefs = this.__store.getSchemaDefinitionService().relationshipsDefinitionFor({
|
|
2051
|
+
type: this.modelName
|
|
2052
|
+
});
|
|
2053
|
+
Object.keys(relationshipDefs).forEach(key => {
|
|
2054
|
+
callback.call(binding, key, relationshipDefs[key]);
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2057
|
+
eachTransformedAttribute(callback, binding) {
|
|
2058
|
+
const attrDefs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({
|
|
2059
|
+
type: this.modelName
|
|
2060
|
+
});
|
|
2061
|
+
Object.keys(attrDefs).forEach(key => {
|
|
2062
|
+
if (attrDefs[key].type) {
|
|
2063
|
+
callback.call(binding, key, attrDefs[key].type);
|
|
2064
|
+
}
|
|
2065
|
+
});
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
var _cache = /*#__PURE__*/_classPrivateFieldKey("cache");
|
|
2069
|
+
/**
|
|
2070
|
+
* The CacheManager wraps a Cache enforcing that only
|
|
2071
|
+
* the public API surface area is exposed.
|
|
2072
|
+
*
|
|
2073
|
+
* Hence, it is the value of `Store.cache`, wrapping
|
|
2074
|
+
* the cache instance returned by `Store.createCache`.
|
|
2075
|
+
*
|
|
2076
|
+
* It handles translating between cache versions when
|
|
2077
|
+
* necessary, for instance when a Store is configured
|
|
2078
|
+
* to use both a v1 and a v2 cache depending on some
|
|
2079
|
+
* heuristic.
|
|
2080
|
+
*
|
|
2081
|
+
* Starting with the v2 spec, the cache is designed such
|
|
2082
|
+
* that it must be implemented as a singleton.
|
|
2083
|
+
*
|
|
2084
|
+
* @class CacheManager
|
|
2085
|
+
* @public
|
|
2086
|
+
*/
|
|
2087
|
+
class CacheManager {
|
|
2088
|
+
constructor(cache) {
|
|
2089
|
+
this.version = '2';
|
|
2090
|
+
Object.defineProperty(this, _cache, {
|
|
2091
|
+
writable: true,
|
|
2092
|
+
value: void 0
|
|
2093
|
+
});
|
|
2094
|
+
/**
|
|
2095
|
+
* Query the cache for whether a given resource has been deleted and that deletion
|
|
2096
|
+
* has also been persisted.
|
|
2097
|
+
*
|
|
2098
|
+
* @method isDeletionCommitted
|
|
2099
|
+
* @public
|
|
2100
|
+
* @param identifier
|
|
2101
|
+
* @returns {boolean}
|
|
2102
|
+
*/
|
|
2103
|
+
this.isDel = void 0;
|
|
2104
|
+
_classPrivateFieldBase(this, _cache)[_cache] = cache;
|
|
2382
2105
|
}
|
|
2383
2106
|
|
|
2107
|
+
// Cache Management
|
|
2108
|
+
// ================
|
|
2109
|
+
|
|
2384
2110
|
/**
|
|
2385
|
-
*
|
|
2111
|
+
* Cache the response to a request
|
|
2386
2112
|
*
|
|
2387
|
-
*
|
|
2113
|
+
* Unlike `store.push` which has UPSERT
|
|
2114
|
+
* semantics, `put` has `replace` semantics similar to
|
|
2115
|
+
* the `http` method `PUT`
|
|
2116
|
+
*
|
|
2117
|
+
* the individually cacheabl
|
|
2118
|
+
* e resource data it may contain
|
|
2119
|
+
* should upsert, but the document data surrounding it should
|
|
2120
|
+
* fully replace any existing information
|
|
2121
|
+
*
|
|
2122
|
+
* Note that in order to support inserting arbitrary data
|
|
2123
|
+
* to the cache that did not originate from a request `put`
|
|
2124
|
+
* should expect to sometimes encounter a document with only
|
|
2125
|
+
* a `content` member and therefor must not assume the existence
|
|
2126
|
+
* of `request` and `response` on the document.
|
|
2127
|
+
*
|
|
2128
|
+
* @method put
|
|
2129
|
+
* @param {StructuredDocument} doc
|
|
2130
|
+
* @returns {ResourceDocument}
|
|
2388
2131
|
* @public
|
|
2389
|
-
* @param identifier
|
|
2390
|
-
* @returns {boolean}
|
|
2391
2132
|
*/
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
return _classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.isEmpty?.(identifier || _classPrivateFieldBase(this, _identifier)[_identifier]) || false : cache.isEmpty(identifier || _classPrivateFieldBase(this, _identifier)[_identifier]);
|
|
2133
|
+
put(doc) {
|
|
2134
|
+
return _classPrivateFieldBase(this, _cache)[_cache].put(doc);
|
|
2395
2135
|
}
|
|
2396
2136
|
|
|
2397
2137
|
/**
|
|
2398
|
-
*
|
|
2399
|
-
* yet persisted.
|
|
2138
|
+
* Perform an operation on the cache to update the remote state.
|
|
2400
2139
|
*
|
|
2401
|
-
*
|
|
2140
|
+
* Note: currently the only valid operation is a MergeOperation
|
|
2141
|
+
* which occurs when a collision of identifiers is detected.
|
|
2142
|
+
*
|
|
2143
|
+
* @method patch
|
|
2402
2144
|
* @public
|
|
2403
|
-
* @param
|
|
2404
|
-
* @returns {
|
|
2145
|
+
* @param op the operation to perform
|
|
2146
|
+
* @returns {void}
|
|
2405
2147
|
*/
|
|
2406
|
-
|
|
2407
|
-
|
|
2148
|
+
patch(op) {
|
|
2149
|
+
_classPrivateFieldBase(this, _cache)[_cache].patch(op);
|
|
2408
2150
|
}
|
|
2409
2151
|
|
|
2410
2152
|
/**
|
|
2411
|
-
*
|
|
2412
|
-
*
|
|
2153
|
+
* Update resource data with a local mutation. Currently supports operations
|
|
2154
|
+
* on relationships only.
|
|
2413
2155
|
*
|
|
2414
|
-
* @method
|
|
2156
|
+
* @method mutate
|
|
2415
2157
|
* @public
|
|
2416
|
-
* @param
|
|
2417
|
-
* @returns {boolean}
|
|
2158
|
+
* @param mutation
|
|
2418
2159
|
*/
|
|
2419
|
-
|
|
2420
|
-
|
|
2160
|
+
mutate(mutation) {
|
|
2161
|
+
_classPrivateFieldBase(this, _cache)[_cache].mutate(mutation);
|
|
2421
2162
|
}
|
|
2422
2163
|
|
|
2423
2164
|
/**
|
|
2424
|
-
*
|
|
2425
|
-
*
|
|
2165
|
+
* Peek resource data from the Cache.
|
|
2166
|
+
*
|
|
2167
|
+
* In development, if the return value
|
|
2168
|
+
* is JSON the return value
|
|
2169
|
+
* will be deep-cloned and deep-frozen
|
|
2170
|
+
* to prevent mutation thereby enforcing cache
|
|
2171
|
+
* Immutability.
|
|
2172
|
+
*
|
|
2173
|
+
* This form of peek is useful for implementations
|
|
2174
|
+
* that want to feed raw-data from cache to the UI
|
|
2175
|
+
* or which want to interact with a blob of data
|
|
2176
|
+
* directly from the presentation cache.
|
|
2177
|
+
*
|
|
2178
|
+
* An implementation might want to do this because
|
|
2179
|
+
* de-referencing records which read from their own
|
|
2180
|
+
* blob is generally safer because the record does
|
|
2181
|
+
* not require retainining connections to the Store
|
|
2182
|
+
* and Cache to present data on a per-field basis.
|
|
2183
|
+
*
|
|
2184
|
+
* This generally takes the place of `getAttr` as
|
|
2185
|
+
* an API and may even take the place of `getRelationship`
|
|
2186
|
+
* depending on implementation specifics, though this
|
|
2187
|
+
* latter usage is less recommended due to the advantages
|
|
2188
|
+
* of the Graph handling necessary entanglements and
|
|
2189
|
+
* notifications for relational data.
|
|
2426
2190
|
*
|
|
2427
|
-
* @method
|
|
2191
|
+
* @method peek
|
|
2428
2192
|
* @public
|
|
2429
|
-
* @param identifier
|
|
2430
|
-
* @returns {
|
|
2193
|
+
* @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
|
|
2194
|
+
* @returns {ResourceDocument | ResourceBlob | null} the known resource data
|
|
2431
2195
|
*/
|
|
2432
|
-
|
|
2433
|
-
return _classPrivateFieldBase(this, _cache)[_cache].isDeletionCommitted(identifier || _classPrivateFieldBase(this, _identifier)[_identifier]);
|
|
2434
|
-
}
|
|
2435
|
-
}
|
|
2436
|
-
function _isDeprecated2(cache) {
|
|
2437
|
-
let version = cache.version || '1';
|
|
2438
|
-
return version !== this.version;
|
|
2439
|
-
}
|
|
2440
|
-
var _cache3 = /*#__PURE__*/_classPrivateFieldKey("cache");
|
|
2441
|
-
class SingletonCacheManager {
|
|
2442
|
-
constructor(cache) {
|
|
2443
|
-
this.version = '2';
|
|
2444
|
-
Object.defineProperty(this, _cache3, {
|
|
2445
|
-
writable: true,
|
|
2446
|
-
value: void 0
|
|
2447
|
-
});
|
|
2448
|
-
_classPrivateFieldBase(this, _cache3)[_cache3] = cache;
|
|
2449
|
-
}
|
|
2450
|
-
put(doc) {
|
|
2451
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].put(doc);
|
|
2452
|
-
}
|
|
2196
|
+
|
|
2453
2197
|
peek(identifier) {
|
|
2454
|
-
return _classPrivateFieldBase(this,
|
|
2198
|
+
return _classPrivateFieldBase(this, _cache)[_cache].peek(identifier);
|
|
2455
2199
|
}
|
|
2200
|
+
|
|
2201
|
+
/**
|
|
2202
|
+
* Peek the Cache for the existing request data associated with
|
|
2203
|
+
* a cacheable request
|
|
2204
|
+
*
|
|
2205
|
+
* @method peekRequest
|
|
2206
|
+
* @param {StableDocumentIdentifier}
|
|
2207
|
+
* @returns {StableDocumentIdentifier | null}
|
|
2208
|
+
* @public
|
|
2209
|
+
*/
|
|
2456
2210
|
peekRequest(identifier) {
|
|
2457
|
-
return _classPrivateFieldBase(this,
|
|
2458
|
-
}
|
|
2459
|
-
fork() {
|
|
2460
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].fork();
|
|
2461
|
-
}
|
|
2462
|
-
merge(cache) {
|
|
2463
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].merge(cache);
|
|
2464
|
-
}
|
|
2465
|
-
diff() {
|
|
2466
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].diff();
|
|
2467
|
-
}
|
|
2468
|
-
dump() {
|
|
2469
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].dump();
|
|
2470
|
-
}
|
|
2471
|
-
hydrate(stream) {
|
|
2472
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].hydrate(stream);
|
|
2211
|
+
return _classPrivateFieldBase(this, _cache)[_cache].peekRequest(identifier);
|
|
2473
2212
|
}
|
|
2474
2213
|
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2214
|
+
/**
|
|
2215
|
+
* Push resource data from a remote source into the cache for this identifier
|
|
2216
|
+
*
|
|
2217
|
+
* @method upsert
|
|
2218
|
+
* @public
|
|
2219
|
+
* @param identifier
|
|
2220
|
+
* @param data
|
|
2221
|
+
* @param hasRecord
|
|
2222
|
+
* @returns {void | string[]} if `hasRecord` is true then calculated key changes should be returned
|
|
2223
|
+
*/
|
|
2478
2224
|
upsert(identifier, data, hasRecord) {
|
|
2479
|
-
return _classPrivateFieldBase(this,
|
|
2480
|
-
}
|
|
2481
|
-
patch(op) {
|
|
2482
|
-
_classPrivateFieldBase(this, _cache3)[_cache3].patch(op);
|
|
2483
|
-
}
|
|
2484
|
-
clientDidCreate(identifier, options) {
|
|
2485
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].clientDidCreate(identifier, options);
|
|
2486
|
-
}
|
|
2487
|
-
willCommit(identifier) {
|
|
2488
|
-
_classPrivateFieldBase(this, _cache3)[_cache3].willCommit(identifier);
|
|
2489
|
-
}
|
|
2490
|
-
didCommit(identifier, data) {
|
|
2491
|
-
_classPrivateFieldBase(this, _cache3)[_cache3].didCommit(identifier, data);
|
|
2492
|
-
}
|
|
2493
|
-
commitWasRejected(identifier, errors) {
|
|
2494
|
-
_classPrivateFieldBase(this, _cache3)[_cache3].commitWasRejected(identifier, errors);
|
|
2495
|
-
}
|
|
2496
|
-
unloadRecord(identifier) {
|
|
2497
|
-
_classPrivateFieldBase(this, _cache3)[_cache3].unloadRecord(identifier);
|
|
2225
|
+
return _classPrivateFieldBase(this, _cache)[_cache].upsert(identifier, data, hasRecord);
|
|
2498
2226
|
}
|
|
2499
2227
|
|
|
2500
|
-
//
|
|
2501
|
-
//
|
|
2228
|
+
// Cache Forking Support
|
|
2229
|
+
// =====================
|
|
2502
2230
|
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].rollbackAttrs(identifier);
|
|
2517
|
-
}
|
|
2518
|
-
getRelationship(identifier, propertyName) {
|
|
2519
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].getRelationship(identifier, propertyName);
|
|
2520
|
-
}
|
|
2521
|
-
mutate(mutation) {
|
|
2522
|
-
_classPrivateFieldBase(this, _cache3)[_cache3].mutate(mutation);
|
|
2231
|
+
/**
|
|
2232
|
+
* Create a fork of the cache from the current state.
|
|
2233
|
+
*
|
|
2234
|
+
* Applications should typically not call this method themselves,
|
|
2235
|
+
* preferring instead to fork at the Store level, which will
|
|
2236
|
+
* utilize this method to fork the cache.
|
|
2237
|
+
*
|
|
2238
|
+
* @method fork
|
|
2239
|
+
* @public
|
|
2240
|
+
* @returns Promise<Cache>
|
|
2241
|
+
*/
|
|
2242
|
+
fork() {
|
|
2243
|
+
return _classPrivateFieldBase(this, _cache)[_cache].fork();
|
|
2523
2244
|
}
|
|
2524
2245
|
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
return _classPrivateFieldBase(this,
|
|
2539
|
-
}
|
|
2540
|
-
isDeleted(identifier) {
|
|
2541
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].isDeleted(identifier);
|
|
2542
|
-
}
|
|
2543
|
-
isDeletionCommitted(identifier) {
|
|
2544
|
-
return _classPrivateFieldBase(this, _cache3)[_cache3].isDeletionCommitted(identifier);
|
|
2545
|
-
}
|
|
2546
|
-
}
|
|
2547
|
-
function constructResource(type, id, lid) {
|
|
2548
|
-
if (typeof type === 'object' && type !== null) {
|
|
2549
|
-
let resource = type;
|
|
2550
|
-
if (isStableIdentifier(resource)) {
|
|
2551
|
-
return resource;
|
|
2552
|
-
}
|
|
2553
|
-
if ('id' in resource) {
|
|
2554
|
-
resource.id = coerceId(resource.id);
|
|
2555
|
-
}
|
|
2556
|
-
assert('Expected either id or lid to be a valid string', 'id' in resource && isNonEmptyString(resource.id) || isNonEmptyString(resource.lid));
|
|
2557
|
-
assert('if id is present, the type must be a string', !('id' in resource) || typeof resource.type === 'string');
|
|
2558
|
-
return resource;
|
|
2559
|
-
} else {
|
|
2560
|
-
const trueId = coerceId(id);
|
|
2561
|
-
if (!isNonEmptyString(trueId)) {
|
|
2562
|
-
if (isNonEmptyString(lid)) {
|
|
2563
|
-
return {
|
|
2564
|
-
lid
|
|
2565
|
-
};
|
|
2566
|
-
}
|
|
2567
|
-
throw new Error('Expected either id or lid to be a valid string');
|
|
2568
|
-
}
|
|
2569
|
-
assert('type must be a string', typeof type === 'string');
|
|
2570
|
-
if (isNonEmptyString(lid)) {
|
|
2571
|
-
return {
|
|
2572
|
-
type,
|
|
2573
|
-
id: trueId,
|
|
2574
|
-
lid
|
|
2575
|
-
};
|
|
2576
|
-
}
|
|
2577
|
-
return {
|
|
2578
|
-
type,
|
|
2579
|
-
id: trueId
|
|
2580
|
-
};
|
|
2581
|
-
}
|
|
2582
|
-
}
|
|
2583
|
-
|
|
2584
|
-
/**
|
|
2585
|
-
@module @ember-data/store
|
|
2586
|
-
*/
|
|
2587
|
-
|
|
2588
|
-
class LegacyWrapper {
|
|
2589
|
-
constructor(_store) {
|
|
2590
|
-
this._store = _store;
|
|
2591
|
-
this._willNotify = false;
|
|
2592
|
-
this._pendingNotifies = new Map();
|
|
2593
|
-
}
|
|
2594
|
-
get identifierCache() {
|
|
2595
|
-
return this._store.identifierCache;
|
|
2596
|
-
}
|
|
2597
|
-
_scheduleNotification(identifier, key) {
|
|
2598
|
-
let pending = this._pendingNotifies.get(identifier);
|
|
2599
|
-
if (!pending) {
|
|
2600
|
-
pending = new Set();
|
|
2601
|
-
this._pendingNotifies.set(identifier, pending);
|
|
2602
|
-
}
|
|
2603
|
-
pending.add(key);
|
|
2604
|
-
if (this._willNotify === true) {
|
|
2605
|
-
return;
|
|
2606
|
-
}
|
|
2607
|
-
this._willNotify = true;
|
|
2608
|
-
// it's possible a RecordData adhoc notifies us,
|
|
2609
|
-
// in which case we sync flush
|
|
2610
|
-
if (this._store._cbs) {
|
|
2611
|
-
this._store._schedule('notify', () => this._flushNotifications());
|
|
2612
|
-
} else {
|
|
2613
|
-
this._flushNotifications();
|
|
2614
|
-
}
|
|
2615
|
-
}
|
|
2616
|
-
_flushNotifications() {
|
|
2617
|
-
if (this._willNotify === false) {
|
|
2618
|
-
return;
|
|
2619
|
-
}
|
|
2620
|
-
let pending = this._pendingNotifies;
|
|
2621
|
-
this._pendingNotifies = new Map();
|
|
2622
|
-
this._willNotify = false;
|
|
2623
|
-
pending.forEach((set, identifier) => {
|
|
2624
|
-
set.forEach(key => {
|
|
2625
|
-
this._store.notifications.notify(identifier, 'relationships', key);
|
|
2626
|
-
});
|
|
2627
|
-
});
|
|
2628
|
-
}
|
|
2629
|
-
notifyChange(identifier, namespace, key) {
|
|
2630
|
-
assert(`Expected a stable identifier`, isStableIdentifier(identifier) || isDocumentIdentifier(identifier));
|
|
2631
|
-
|
|
2632
|
-
// TODO do we still get value from this?
|
|
2633
|
-
if (namespace === 'relationships' && key) {
|
|
2634
|
-
this._scheduleNotification(identifier, key);
|
|
2635
|
-
return;
|
|
2636
|
-
}
|
|
2637
|
-
|
|
2638
|
-
// @ts-expect-error
|
|
2639
|
-
this._store.notifications.notify(identifier, namespace, key);
|
|
2640
|
-
}
|
|
2641
|
-
notifyErrorsChange(type, id, lid) {
|
|
2642
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2643
|
-
deprecate(`StoreWrapper.notifyErrorsChange has been deprecated in favor of StoreWrapper.notifyChange`, false, {
|
|
2644
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2645
|
-
for: 'ember-data',
|
|
2646
|
-
until: '5.0',
|
|
2647
|
-
since: {
|
|
2648
|
-
enabled: '4.7',
|
|
2649
|
-
available: '4.7'
|
|
2650
|
-
}
|
|
2651
|
-
});
|
|
2652
|
-
}
|
|
2653
|
-
const resource = constructResource(type, id, lid);
|
|
2654
|
-
const identifier = this.identifierCache.getOrCreateRecordIdentifier(resource);
|
|
2655
|
-
this._store.notifications.notify(identifier, 'errors');
|
|
2656
|
-
}
|
|
2657
|
-
attributesDefinitionFor(type) {
|
|
2658
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2659
|
-
deprecate(`StoreWrapper.attributesDefinitionFor has been deprecated in favor of StoreWrapper.getSchemaDefinitionService().attributesDefinitionFor`, false, {
|
|
2660
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2661
|
-
for: 'ember-data',
|
|
2662
|
-
until: '5.0',
|
|
2663
|
-
since: {
|
|
2664
|
-
enabled: '4.7',
|
|
2665
|
-
available: '4.7'
|
|
2666
|
-
}
|
|
2667
|
-
});
|
|
2668
|
-
}
|
|
2669
|
-
return this._store.getSchemaDefinitionService().attributesDefinitionFor({
|
|
2670
|
-
type
|
|
2671
|
-
});
|
|
2672
|
-
}
|
|
2673
|
-
relationshipsDefinitionFor(type) {
|
|
2674
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2675
|
-
deprecate(`StoreWrapper.relationshipsDefinitionFor has been deprecated in favor of StoreWrapper.getSchemaDefinitionService().relationshipsDefinitionFor`, false, {
|
|
2676
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2677
|
-
for: 'ember-data',
|
|
2678
|
-
until: '5.0',
|
|
2679
|
-
since: {
|
|
2680
|
-
enabled: '4.7',
|
|
2681
|
-
available: '4.7'
|
|
2682
|
-
}
|
|
2683
|
-
});
|
|
2684
|
-
}
|
|
2685
|
-
return this._store.getSchemaDefinitionService().relationshipsDefinitionFor({
|
|
2686
|
-
type
|
|
2687
|
-
});
|
|
2688
|
-
}
|
|
2689
|
-
getSchemaDefinitionService() {
|
|
2690
|
-
return this._store.getSchemaDefinitionService();
|
|
2691
|
-
}
|
|
2692
|
-
notifyPropertyChange(type, id, lid, key) {
|
|
2693
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2694
|
-
deprecate(`StoreWrapper.notifyPropertyChange has been deprecated in favor of StoreWrapper.notifyChange`, false, {
|
|
2695
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2696
|
-
for: 'ember-data',
|
|
2697
|
-
until: '5.0',
|
|
2698
|
-
since: {
|
|
2699
|
-
enabled: '4.7',
|
|
2700
|
-
available: '4.7'
|
|
2701
|
-
}
|
|
2702
|
-
});
|
|
2703
|
-
}
|
|
2704
|
-
const resource = constructResource(type, id, lid);
|
|
2705
|
-
const identifier = this.identifierCache.getOrCreateRecordIdentifier(resource);
|
|
2706
|
-
this._store.notifications.notify(identifier, 'attributes', key);
|
|
2707
|
-
}
|
|
2708
|
-
notifyHasManyChange(type, id, lid, key) {
|
|
2709
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2710
|
-
deprecate(`StoreWrapper.notifyHasManyChange has been deprecated in favor of StoreWrapper.notifyChange`, false, {
|
|
2711
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2712
|
-
for: 'ember-data',
|
|
2713
|
-
until: '5.0',
|
|
2714
|
-
since: {
|
|
2715
|
-
enabled: '4.7',
|
|
2716
|
-
available: '4.7'
|
|
2717
|
-
}
|
|
2718
|
-
});
|
|
2719
|
-
}
|
|
2720
|
-
const resource = constructResource(type, id, lid);
|
|
2721
|
-
const identifier = this.identifierCache.getOrCreateRecordIdentifier(resource);
|
|
2722
|
-
this._scheduleNotification(identifier, key);
|
|
2723
|
-
}
|
|
2724
|
-
notifyBelongsToChange(type, id, lid, key) {
|
|
2725
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2726
|
-
deprecate(`StoreWrapper.notifyBelongsToChange has been deprecated in favor of StoreWrapper.notifyChange`, false, {
|
|
2727
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2728
|
-
for: 'ember-data',
|
|
2729
|
-
until: '5.0',
|
|
2730
|
-
since: {
|
|
2731
|
-
enabled: '4.7',
|
|
2732
|
-
available: '4.7'
|
|
2733
|
-
}
|
|
2734
|
-
});
|
|
2735
|
-
}
|
|
2736
|
-
const resource = constructResource(type, id, lid);
|
|
2737
|
-
const identifier = this.identifierCache.getOrCreateRecordIdentifier(resource);
|
|
2738
|
-
this._scheduleNotification(identifier, key);
|
|
2739
|
-
}
|
|
2740
|
-
notifyStateChange(type, id, lid, key) {
|
|
2741
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2742
|
-
deprecate(`StoreWrapper.notifyStateChange has been deprecated in favor of StoreWrapper.notifyChange`, false, {
|
|
2743
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2744
|
-
for: 'ember-data',
|
|
2745
|
-
until: '5.0',
|
|
2746
|
-
since: {
|
|
2747
|
-
enabled: '4.7',
|
|
2748
|
-
available: '4.7'
|
|
2749
|
-
}
|
|
2750
|
-
});
|
|
2751
|
-
}
|
|
2752
|
-
const resource = constructResource(type, id, lid);
|
|
2753
|
-
const identifier = this.identifierCache.getOrCreateRecordIdentifier(resource);
|
|
2754
|
-
this._store.notifications.notify(identifier, 'state');
|
|
2755
|
-
}
|
|
2756
|
-
recordDataFor(type, id, lid) {
|
|
2757
|
-
let identifier;
|
|
2758
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2759
|
-
if (!isStableIdentifier(type)) {
|
|
2760
|
-
// we also deprecate create capability. This behavior was problematic because
|
|
2761
|
-
// there's no outside association between this RecordData and an Identifier.
|
|
2762
|
-
// It's likely a mistake when we hit this codepath, but we said in an early
|
|
2763
|
-
// RFC we'd allow this.
|
|
2764
|
-
// With V2 we are enforcing someone to use the record-data and identifier-cache APIs to
|
|
2765
|
-
// create a new identifier and then call clientDidCreate on the RecordData
|
|
2766
|
-
// instead.
|
|
2767
|
-
identifier = !id && !lid ? this.identifierCache.createIdentifierForNewRecord({
|
|
2768
|
-
type: type
|
|
2769
|
-
}) : this.identifierCache.getOrCreateRecordIdentifier(constructResource(type, id, lid));
|
|
2770
|
-
} else {
|
|
2771
|
-
identifier = type;
|
|
2772
|
-
}
|
|
2773
|
-
} else {
|
|
2774
|
-
assert(`Expected a stable identifier`, isStableIdentifier(type));
|
|
2775
|
-
identifier = type;
|
|
2776
|
-
}
|
|
2777
|
-
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._store._instanceCache.getResourceCache(identifier) : this._store.cache;
|
|
2778
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2779
|
-
if (!id && !lid && typeof type === 'string') {
|
|
2780
|
-
cache.clientDidCreate(identifier);
|
|
2781
|
-
this._store.recordArrayManager.identifierAdded(identifier);
|
|
2782
|
-
}
|
|
2783
|
-
}
|
|
2784
|
-
return cache;
|
|
2785
|
-
}
|
|
2786
|
-
setRecordId(type, id, lid) {
|
|
2787
|
-
let identifier;
|
|
2788
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2789
|
-
if (!isStableIdentifier(type)) {
|
|
2790
|
-
const modelName = normalizeModelName$1(type);
|
|
2791
|
-
const resource = constructResource(modelName, null, coerceId(lid));
|
|
2792
|
-
identifier = this.identifierCache.peekRecordIdentifier(resource);
|
|
2793
|
-
} else {
|
|
2794
|
-
identifier = type;
|
|
2795
|
-
}
|
|
2796
|
-
} else {
|
|
2797
|
-
assert(`Expected a stable identifier`, isStableIdentifier(type));
|
|
2798
|
-
identifier = type;
|
|
2799
|
-
}
|
|
2800
|
-
assert(`Unable to find an identifier to update the ID for for ${String(lid)}`, identifier);
|
|
2801
|
-
this._store._instanceCache.setRecordId(identifier, id);
|
|
2802
|
-
}
|
|
2803
|
-
isRecordInUse(type, id, lid) {
|
|
2804
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2805
|
-
deprecate(`StoreWrapper.isRecordInUSe has been deprecated in favor of StoreWrapper.hasRecord`, false, {
|
|
2806
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2807
|
-
for: 'ember-data',
|
|
2808
|
-
until: '5.0',
|
|
2809
|
-
since: {
|
|
2810
|
-
enabled: '4.7',
|
|
2811
|
-
available: '4.7'
|
|
2812
|
-
}
|
|
2813
|
-
});
|
|
2814
|
-
}
|
|
2815
|
-
const resource = constructResource(type, id, lid);
|
|
2816
|
-
const identifier = this.identifierCache.peekRecordIdentifier(resource);
|
|
2817
|
-
const record = identifier && this._store._instanceCache.peek({
|
|
2818
|
-
identifier,
|
|
2819
|
-
bucket: 'record'
|
|
2820
|
-
});
|
|
2821
|
-
return record ? !(record.isDestroyed || record.isDestroying) : false;
|
|
2822
|
-
}
|
|
2823
|
-
hasRecord(identifier) {
|
|
2824
|
-
return Boolean(this._store._instanceCache.peek({
|
|
2825
|
-
identifier,
|
|
2826
|
-
bucket: 'record'
|
|
2827
|
-
}));
|
|
2828
|
-
}
|
|
2829
|
-
disconnectRecord(type, id, lid) {
|
|
2830
|
-
let identifier;
|
|
2831
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
2832
|
-
if (typeof type === 'string') {
|
|
2833
|
-
deprecate(`StoreWrapper.disconnectRecord(<type>) has been deprecated in favor of StoreWrapper.disconnectRecord(<identifier>)`, false, {
|
|
2834
|
-
id: 'ember-data:deprecate-v1cache-store-apis',
|
|
2835
|
-
for: 'ember-data',
|
|
2836
|
-
until: '5.0',
|
|
2837
|
-
since: {
|
|
2838
|
-
enabled: '4.7',
|
|
2839
|
-
available: '4.7'
|
|
2840
|
-
}
|
|
2841
|
-
});
|
|
2842
|
-
let resource = constructResource(type, id, lid);
|
|
2843
|
-
identifier = this.identifierCache.peekRecordIdentifier(resource);
|
|
2844
|
-
} else {
|
|
2845
|
-
identifier = type;
|
|
2846
|
-
}
|
|
2847
|
-
} else {
|
|
2848
|
-
identifier = type;
|
|
2849
|
-
}
|
|
2850
|
-
assert(`Expected a stable identifier`, isStableIdentifier(identifier));
|
|
2851
|
-
this._store._instanceCache.disconnect(identifier);
|
|
2852
|
-
this._pendingNotifies.delete(identifier);
|
|
2853
|
-
}
|
|
2854
|
-
}
|
|
2855
|
-
class V2CacheStoreWrapper {
|
|
2856
|
-
constructor(_store) {
|
|
2857
|
-
this._store = _store;
|
|
2858
|
-
this._willNotify = false;
|
|
2859
|
-
this._pendingNotifies = new Map();
|
|
2860
|
-
}
|
|
2861
|
-
get identifierCache() {
|
|
2862
|
-
return this._store.identifierCache;
|
|
2863
|
-
}
|
|
2864
|
-
_scheduleNotification(identifier, key) {
|
|
2865
|
-
let pending = this._pendingNotifies.get(identifier);
|
|
2866
|
-
if (!pending) {
|
|
2867
|
-
pending = new Set();
|
|
2868
|
-
this._pendingNotifies.set(identifier, pending);
|
|
2869
|
-
}
|
|
2870
|
-
pending.add(key);
|
|
2871
|
-
if (this._willNotify === true) {
|
|
2872
|
-
return;
|
|
2873
|
-
}
|
|
2874
|
-
this._willNotify = true;
|
|
2875
|
-
// it's possible a cache adhoc notifies us,
|
|
2876
|
-
// in which case we sync flush
|
|
2877
|
-
if (this._store._cbs) {
|
|
2878
|
-
this._store._schedule('notify', () => this._flushNotifications());
|
|
2879
|
-
} else {
|
|
2880
|
-
this._flushNotifications();
|
|
2881
|
-
}
|
|
2882
|
-
}
|
|
2883
|
-
_flushNotifications() {
|
|
2884
|
-
if (this._willNotify === false) {
|
|
2885
|
-
return;
|
|
2886
|
-
}
|
|
2887
|
-
let pending = this._pendingNotifies;
|
|
2888
|
-
this._pendingNotifies = new Map();
|
|
2889
|
-
this._willNotify = false;
|
|
2890
|
-
pending.forEach((set, identifier) => {
|
|
2891
|
-
set.forEach(key => {
|
|
2892
|
-
this._store.notifications.notify(identifier, 'relationships', key);
|
|
2893
|
-
});
|
|
2894
|
-
});
|
|
2895
|
-
}
|
|
2896
|
-
notifyChange(identifier, namespace, key) {
|
|
2897
|
-
assert(`Expected a stable identifier`, isStableIdentifier(identifier) || isDocumentIdentifier(identifier));
|
|
2898
|
-
|
|
2899
|
-
// TODO do we still get value from this?
|
|
2900
|
-
if (namespace === 'relationships' && key) {
|
|
2901
|
-
this._scheduleNotification(identifier, key);
|
|
2902
|
-
return;
|
|
2903
|
-
}
|
|
2904
|
-
|
|
2905
|
-
// @ts-expect-error
|
|
2906
|
-
this._store.notifications.notify(identifier, namespace, key);
|
|
2907
|
-
}
|
|
2908
|
-
getSchemaDefinitionService() {
|
|
2909
|
-
return this._store.getSchemaDefinitionService();
|
|
2910
|
-
}
|
|
2911
|
-
recordDataFor(identifier) {
|
|
2912
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA)) {
|
|
2913
|
-
deprecate(`StoreWrapper.recordDataFor is deprecated. With Singleton Cache, this method is no longer needed as the caller is its own cache reference.`, false, {
|
|
2914
|
-
for: '@ember-data/store',
|
|
2915
|
-
id: 'ember-data:deprecate-record-data-for',
|
|
2916
|
-
since: {
|
|
2917
|
-
available: '4.10',
|
|
2918
|
-
enabled: '4.10'
|
|
2919
|
-
},
|
|
2920
|
-
until: '5.0'
|
|
2921
|
-
});
|
|
2922
|
-
}
|
|
2923
|
-
assert(`Expected a stable identifier`, isStableIdentifier(identifier));
|
|
2924
|
-
return macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._store._instanceCache.getResourceCache(identifier) : void 0;
|
|
2925
|
-
}
|
|
2926
|
-
setRecordId(identifier, id) {
|
|
2927
|
-
assert(`Expected a stable identifier`, isStableIdentifier(identifier));
|
|
2928
|
-
this._store._instanceCache.setRecordId(identifier, id);
|
|
2929
|
-
}
|
|
2930
|
-
hasRecord(identifier) {
|
|
2931
|
-
return Boolean(this._store._instanceCache.peek({
|
|
2932
|
-
identifier,
|
|
2933
|
-
bucket: 'record'
|
|
2934
|
-
}));
|
|
2935
|
-
}
|
|
2936
|
-
disconnectRecord(identifier) {
|
|
2937
|
-
assert(`Expected a stable identifier`, isStableIdentifier(identifier));
|
|
2938
|
-
this._store._instanceCache.disconnect(identifier);
|
|
2939
|
-
this._pendingNotifies.delete(identifier);
|
|
2940
|
-
}
|
|
2941
|
-
}
|
|
2942
|
-
const CacheStoreWrapper = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS) ? LegacyWrapper : V2CacheStoreWrapper;
|
|
2943
|
-
let _peekGraph;
|
|
2944
|
-
if (macroCondition(getOwnConfig().packages.HAS_GRAPH_PACKAGE)) {
|
|
2945
|
-
let __peekGraph;
|
|
2946
|
-
_peekGraph = wrapper => {
|
|
2947
|
-
let a = importSync('@ember-data/graph/-private').peekGraph;
|
|
2948
|
-
__peekGraph = __peekGraph || a;
|
|
2949
|
-
return __peekGraph(wrapper);
|
|
2950
|
-
};
|
|
2951
|
-
}
|
|
2952
|
-
|
|
2953
|
-
/**
|
|
2954
|
-
@module @ember-data/store
|
|
2955
|
-
*/
|
|
2956
|
-
|
|
2957
|
-
const RecordCache = new Map();
|
|
2958
|
-
function peekRecordIdentifier(record) {
|
|
2959
|
-
return RecordCache.get(record);
|
|
2960
|
-
}
|
|
2961
|
-
|
|
2962
|
-
/**
|
|
2963
|
-
Retrieves the unique referentially-stable [RecordIdentifier](/ember-data/release/classes/StableRecordIdentifier)
|
|
2964
|
-
assigned to the given record instance.
|
|
2965
|
-
```js
|
|
2966
|
-
import { recordIdentifierFor } from "@ember-data/store";
|
|
2967
|
-
// ... gain access to a record, for instance with peekRecord or findRecord
|
|
2968
|
-
const record = store.peekRecord("user", "1");
|
|
2969
|
-
// get the identifier for the record (see docs for StableRecordIdentifier)
|
|
2970
|
-
const identifier = recordIdentifierFor(record);
|
|
2971
|
-
// access the identifier's properties.
|
|
2972
|
-
const { id, type, lid } = identifier;
|
|
2973
|
-
```
|
|
2974
|
-
@method recordIdentifierFor
|
|
2975
|
-
@public
|
|
2976
|
-
@static
|
|
2977
|
-
@for @ember-data/store
|
|
2978
|
-
@param {Object} record a record instance previously obstained from the store.
|
|
2979
|
-
@returns {StableRecordIdentifier}
|
|
2980
|
-
*/
|
|
2981
|
-
function recordIdentifierFor(record) {
|
|
2982
|
-
assert(`${String(record)} is not a record instantiated by @ember-data/store`, RecordCache.has(record));
|
|
2983
|
-
return RecordCache.get(record);
|
|
2984
|
-
}
|
|
2985
|
-
function setRecordIdentifier(record, identifier) {
|
|
2986
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
2987
|
-
if (RecordCache.has(record) && RecordCache.get(record) !== identifier) {
|
|
2988
|
-
throw new Error(`${String(record)} was already assigned an identifier`);
|
|
2989
|
-
}
|
|
2990
|
-
}
|
|
2991
|
-
|
|
2992
|
-
/*
|
|
2993
|
-
It would be nice to do a reverse check here that an identifier has not
|
|
2994
|
-
previously been assigned a record; however, unload + rematerialization
|
|
2995
|
-
prevents us from having a great way of doing so when CustomRecordClasses
|
|
2996
|
-
don't necessarily give us access to a `isDestroyed` for dematerialized
|
|
2997
|
-
instance.
|
|
2998
|
-
*/
|
|
2999
|
-
|
|
3000
|
-
RecordCache.set(record, identifier);
|
|
3001
|
-
}
|
|
3002
|
-
const StoreMap = new Map();
|
|
3003
|
-
function storeFor(record) {
|
|
3004
|
-
const store = StoreMap.get(record);
|
|
3005
|
-
assert(`A record in a disconnected state cannot utilize the store. This typically means the record has been destroyed, most commonly by unloading it.`, store);
|
|
3006
|
-
return store;
|
|
3007
|
-
}
|
|
3008
|
-
class InstanceCache {
|
|
3009
|
-
constructor(store) {
|
|
3010
|
-
this.__instances = {
|
|
3011
|
-
record: new Map(),
|
|
3012
|
-
resourceCache: new Map(),
|
|
3013
|
-
reference: new WeakMap()
|
|
3014
|
-
};
|
|
3015
|
-
this.store = store;
|
|
3016
|
-
this._storeWrapper = new CacheStoreWrapper(this.store);
|
|
3017
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA)) {
|
|
3018
|
-
this.__cacheFor = resource => {
|
|
3019
|
-
// TODO enforce strict
|
|
3020
|
-
const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resource);
|
|
3021
|
-
return this.getResourceCache(identifier);
|
|
3022
|
-
};
|
|
3023
|
-
}
|
|
3024
|
-
store.identifierCache.__configureMerge((identifier, matchedIdentifier, resourceData) => {
|
|
3025
|
-
let keptIdentifier = identifier;
|
|
3026
|
-
if (identifier.id !== matchedIdentifier.id) {
|
|
3027
|
-
keptIdentifier = 'id' in resourceData && identifier.id === resourceData.id ? identifier : matchedIdentifier;
|
|
3028
|
-
} else if (identifier.type !== matchedIdentifier.type) {
|
|
3029
|
-
keptIdentifier = 'type' in resourceData && identifier.type === resourceData.type ? identifier : matchedIdentifier;
|
|
3030
|
-
}
|
|
3031
|
-
let staleIdentifier = identifier === keptIdentifier ? matchedIdentifier : identifier;
|
|
3032
|
-
|
|
3033
|
-
// check for duplicate entities
|
|
3034
|
-
let keptHasRecord = this.__instances.record.has(keptIdentifier);
|
|
3035
|
-
let staleHasRecord = this.__instances.record.has(staleIdentifier);
|
|
3036
|
-
let keptResourceCache = this.__instances.resourceCache.get(keptIdentifier) || null;
|
|
3037
|
-
let staleResourceCache = this.__instances.resourceCache.get(staleIdentifier) || null;
|
|
3038
|
-
|
|
3039
|
-
// we cannot merge entities when both have records
|
|
3040
|
-
// (this may not be strictly true, we could probably swap the cache data the record points at)
|
|
3041
|
-
if (keptHasRecord && staleHasRecord) {
|
|
3042
|
-
// TODO we probably don't need to throw these errors anymore
|
|
3043
|
-
// we can probably just "swap" what data source the abandoned
|
|
3044
|
-
// record points at so long as
|
|
3045
|
-
// it itself is not retained by the store in any way.
|
|
3046
|
-
if ('id' in resourceData) {
|
|
3047
|
-
throw new Error(`Failed to update the 'id' for the RecordIdentifier '${identifier.type}:${String(identifier.id)} (${identifier.lid})' to '${String(resourceData.id)}', because that id is already in use by '${matchedIdentifier.type}:${String(matchedIdentifier.id)} (${matchedIdentifier.lid})'`);
|
|
3048
|
-
}
|
|
3049
|
-
assert(`Failed to update the RecordIdentifier '${identifier.type}:${String(identifier.id)} (${identifier.lid})' to merge with the detected duplicate identifier '${matchedIdentifier.type}:${String(matchedIdentifier.id)} (${String(matchedIdentifier.lid)})'`);
|
|
3050
|
-
}
|
|
3051
|
-
let resourceCache = keptResourceCache || staleResourceCache;
|
|
3052
|
-
if (resourceCache) {
|
|
3053
|
-
resourceCache.patch({
|
|
3054
|
-
op: 'mergeIdentifiers',
|
|
3055
|
-
record: staleIdentifier,
|
|
3056
|
-
value: keptIdentifier
|
|
3057
|
-
});
|
|
3058
|
-
} else if (macroCondition(!getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA)) {
|
|
3059
|
-
this.store.cache.patch({
|
|
3060
|
-
op: 'mergeIdentifiers',
|
|
3061
|
-
record: staleIdentifier,
|
|
3062
|
-
value: keptIdentifier
|
|
3063
|
-
});
|
|
3064
|
-
} else if (macroCondition(getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
|
|
3065
|
-
this.store.cache.patch({
|
|
3066
|
-
op: 'mergeIdentifiers',
|
|
3067
|
-
record: staleIdentifier,
|
|
3068
|
-
value: keptIdentifier
|
|
3069
|
-
});
|
|
3070
|
-
}
|
|
3071
|
-
if (staleResourceCache === null) {
|
|
3072
|
-
return keptIdentifier;
|
|
3073
|
-
}
|
|
3074
|
-
|
|
3075
|
-
/*
|
|
3076
|
-
TODO @runspired consider adding this to make polymorphism even nicer
|
|
3077
|
-
if (HAS_GRAPH_PACKAGE) {
|
|
3078
|
-
if (identifier.type !== matchedIdentifier.type) {
|
|
3079
|
-
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
3080
|
-
graphFor(this).registerPolymorphicType(identifier.type, matchedIdentifier.type);
|
|
3081
|
-
}
|
|
3082
|
-
}
|
|
3083
|
-
*/
|
|
3084
|
-
|
|
3085
|
-
this.unloadRecord(staleIdentifier);
|
|
3086
|
-
return keptIdentifier;
|
|
3087
|
-
});
|
|
3088
|
-
}
|
|
3089
|
-
peek({
|
|
3090
|
-
identifier,
|
|
3091
|
-
bucket
|
|
3092
|
-
}) {
|
|
3093
|
-
return this.__instances[bucket]?.get(identifier);
|
|
3094
|
-
}
|
|
3095
|
-
getRecord(identifier, properties) {
|
|
3096
|
-
let record = this.__instances.record.get(identifier);
|
|
3097
|
-
if (!record) {
|
|
3098
|
-
assert(`Cannot create a new record instance while the store is being destroyed`, !this.store.isDestroying && !this.store.isDestroyed);
|
|
3099
|
-
const cache = this.getResourceCache(identifier);
|
|
3100
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_INSTANTIATE_RECORD_ARGS)) {
|
|
3101
|
-
if (this.store.instantiateRecord.length > 2) {
|
|
3102
|
-
deprecate(`Expected store.instantiateRecord to have an arity of 2. recordDataFor and notificationManager args have been deprecated.`, false, {
|
|
3103
|
-
for: '@ember-data/store',
|
|
3104
|
-
id: 'ember-data:deprecate-instantiate-record-args',
|
|
3105
|
-
since: {
|
|
3106
|
-
available: '4.12',
|
|
3107
|
-
enabled: '4.12'
|
|
3108
|
-
},
|
|
3109
|
-
until: '5.0'
|
|
3110
|
-
});
|
|
3111
|
-
}
|
|
3112
|
-
record = this.store.instantiateRecord(identifier, properties || {},
|
|
3113
|
-
// @ts-expect-error
|
|
3114
|
-
this.__cacheFor, this.store.notifications);
|
|
3115
|
-
} else {
|
|
3116
|
-
record = this.store.instantiateRecord(identifier, properties || {});
|
|
3117
|
-
}
|
|
3118
|
-
setRecordIdentifier(record, identifier);
|
|
3119
|
-
setCacheFor(record, cache);
|
|
3120
|
-
StoreMap.set(record, this.store);
|
|
3121
|
-
this.__instances.record.set(identifier, record);
|
|
3122
|
-
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
3123
|
-
// eslint-disable-next-line no-console
|
|
3124
|
-
console.log(`InstanceCache: created Record for ${String(identifier)}`, properties);
|
|
3125
|
-
}
|
|
3126
|
-
}
|
|
3127
|
-
return record;
|
|
3128
|
-
}
|
|
3129
|
-
getResourceCache(identifier) {
|
|
3130
|
-
if (macroCondition(!getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA)) {
|
|
3131
|
-
const cache = this.store.cache;
|
|
3132
|
-
setCacheFor(identifier, cache);
|
|
3133
|
-
this.__instances.resourceCache.set(identifier, cache);
|
|
3134
|
-
return cache;
|
|
3135
|
-
}
|
|
3136
|
-
let cache = this.__instances.resourceCache.get(identifier);
|
|
3137
|
-
if (cache) {
|
|
3138
|
-
return cache;
|
|
3139
|
-
}
|
|
3140
|
-
if (this.store.createRecordDataFor) {
|
|
3141
|
-
deprecate(`Store.createRecordDataFor(<type>, <id>, <lid>, <storeWrapper>) has been deprecated in favor of Store.createCache(<storeWrapper>)`, false, {
|
|
3142
|
-
id: 'ember-data:deprecate-v1-cache',
|
|
3143
|
-
for: 'ember-data',
|
|
3144
|
-
until: '5.0',
|
|
3145
|
-
since: {
|
|
3146
|
-
enabled: '4.12',
|
|
3147
|
-
available: '4.12'
|
|
3148
|
-
}
|
|
3149
|
-
});
|
|
3150
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
|
|
3151
|
-
if (this.store.createRecordDataFor.length > 2) {
|
|
3152
|
-
let cacheInstance = this.store.createRecordDataFor(identifier.type, identifier.id,
|
|
3153
|
-
// @ts-expect-error
|
|
3154
|
-
identifier.lid, this._storeWrapper);
|
|
3155
|
-
cache = new NonSingletonCacheManager(this.store, cacheInstance, identifier);
|
|
3156
|
-
}
|
|
3157
|
-
}
|
|
3158
|
-
if (!cache) {
|
|
3159
|
-
let cacheInstance = this.store.createRecordDataFor(identifier, this._storeWrapper);
|
|
3160
|
-
cache = cacheInstance.version === '2' ? cacheInstance : new NonSingletonCacheManager(this.store, cacheInstance, identifier);
|
|
3161
|
-
}
|
|
3162
|
-
} else {
|
|
3163
|
-
cache = this.store.cache;
|
|
3164
|
-
}
|
|
3165
|
-
setCacheFor(identifier, cache);
|
|
3166
|
-
this.__instances.resourceCache.set(identifier, cache);
|
|
3167
|
-
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
3168
|
-
// eslint-disable-next-line no-console
|
|
3169
|
-
console.log(`InstanceCache: created Cache for ${String(identifier)}`);
|
|
3170
|
-
}
|
|
3171
|
-
return cache;
|
|
3172
|
-
}
|
|
3173
|
-
getReference(identifier) {
|
|
3174
|
-
let cache = this.__instances.reference;
|
|
3175
|
-
let reference = cache.get(identifier);
|
|
3176
|
-
if (!reference) {
|
|
3177
|
-
reference = new RecordReference(this.store, identifier);
|
|
3178
|
-
cache.set(identifier, reference);
|
|
3179
|
-
}
|
|
3180
|
-
return reference;
|
|
3181
|
-
}
|
|
3182
|
-
recordIsLoaded(identifier, filterDeleted = false) {
|
|
3183
|
-
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this.__instances.resourceCache.get(identifier) || this.cache : this.cache;
|
|
3184
|
-
if (!cache) {
|
|
3185
|
-
return false;
|
|
3186
|
-
}
|
|
3187
|
-
const isNew = cache.isNew(identifier);
|
|
3188
|
-
const isEmpty = cache.isEmpty(identifier);
|
|
3189
|
-
|
|
3190
|
-
// if we are new we must consider ourselves loaded
|
|
3191
|
-
if (isNew) {
|
|
3192
|
-
return !cache.isDeleted(identifier);
|
|
3193
|
-
}
|
|
3194
|
-
// even if we have a past request, if we are now empty we are not loaded
|
|
3195
|
-
// typically this is true after an unloadRecord call
|
|
3196
|
-
|
|
3197
|
-
// if we are not empty, not new && we have a fulfilled request then we are loaded
|
|
3198
|
-
// we should consider allowing for something to be loaded that is simply "not empty".
|
|
3199
|
-
// which is how RecordState currently handles this case; however, RecordState is buggy
|
|
3200
|
-
// in that it does not account for unloading.
|
|
3201
|
-
return filterDeleted && cache.isDeletionCommitted(identifier) ? false : !isEmpty;
|
|
3202
|
-
}
|
|
3203
|
-
disconnect(identifier) {
|
|
3204
|
-
const record = this.__instances.record.get(identifier);
|
|
3205
|
-
assert('Cannot destroy record while it is still materialized', !record || record.isDestroyed || record.isDestroying);
|
|
3206
|
-
if (macroCondition(getOwnConfig().packages.HAS_GRAPH_PACKAGE)) {
|
|
3207
|
-
let graph = _peekGraph(this.store);
|
|
3208
|
-
if (graph) {
|
|
3209
|
-
graph.remove(identifier);
|
|
3210
|
-
}
|
|
3211
|
-
}
|
|
3212
|
-
this.store.identifierCache.forgetRecordIdentifier(identifier);
|
|
3213
|
-
this.__instances.resourceCache.delete(identifier);
|
|
3214
|
-
removeRecordDataFor(identifier);
|
|
3215
|
-
this.store._requestCache._clearEntries(identifier);
|
|
3216
|
-
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
3217
|
-
// eslint-disable-next-line no-console
|
|
3218
|
-
console.log(`InstanceCache: disconnected ${String(identifier)}`);
|
|
3219
|
-
}
|
|
3220
|
-
}
|
|
3221
|
-
unloadRecord(identifier) {
|
|
3222
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
3223
|
-
const requests = this.store.getRequestStateService().getPendingRequestsForRecord(identifier);
|
|
3224
|
-
if (requests.some(req => {
|
|
3225
|
-
return req.type === 'mutation';
|
|
3226
|
-
})) {
|
|
3227
|
-
assert(`You can only unload a record which is not inFlight. '${String(identifier)}'`);
|
|
3228
|
-
}
|
|
3229
|
-
}
|
|
3230
|
-
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
3231
|
-
// eslint-disable-next-line no-console
|
|
3232
|
-
console.groupCollapsed(`InstanceCache: unloading record for ${String(identifier)}`);
|
|
3233
|
-
}
|
|
3234
|
-
|
|
3235
|
-
// TODO is this join still necessary?
|
|
3236
|
-
this.store._join(() => {
|
|
3237
|
-
const record = this.__instances.record.get(identifier);
|
|
3238
|
-
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this.__instances.resourceCache.get(identifier) : this.cache;
|
|
3239
|
-
if (record) {
|
|
3240
|
-
this.store.teardownRecord(record);
|
|
3241
|
-
this.__instances.record.delete(identifier);
|
|
3242
|
-
StoreMap.delete(record);
|
|
3243
|
-
RecordCache.delete(record);
|
|
3244
|
-
removeRecordDataFor(record);
|
|
3245
|
-
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
3246
|
-
// eslint-disable-next-line no-console
|
|
3247
|
-
console.log(`InstanceCache: destroyed record for ${String(identifier)}`);
|
|
3248
|
-
}
|
|
3249
|
-
}
|
|
3250
|
-
if (cache) {
|
|
3251
|
-
cache.unloadRecord(identifier);
|
|
3252
|
-
this.__instances.resourceCache.delete(identifier);
|
|
3253
|
-
removeRecordDataFor(identifier);
|
|
3254
|
-
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
3255
|
-
// eslint-disable-next-line no-console
|
|
3256
|
-
console.log(`InstanceCache: destroyed cache for ${String(identifier)}`);
|
|
3257
|
-
}
|
|
3258
|
-
} else {
|
|
3259
|
-
this.disconnect(identifier);
|
|
3260
|
-
}
|
|
3261
|
-
this.store._requestCache._clearEntries(identifier);
|
|
3262
|
-
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
3263
|
-
// eslint-disable-next-line no-console
|
|
3264
|
-
console.log(`InstanceCache: unloaded RecordData for ${String(identifier)}`);
|
|
3265
|
-
// eslint-disable-next-line no-console
|
|
3266
|
-
console.groupEnd();
|
|
3267
|
-
}
|
|
3268
|
-
});
|
|
3269
|
-
}
|
|
3270
|
-
clear(type) {
|
|
3271
|
-
const cache = this.store.identifierCache._cache;
|
|
3272
|
-
if (type === undefined) {
|
|
3273
|
-
// it would be cool if we could just de-ref cache here
|
|
3274
|
-
// but probably would require WeakRef models to do so.
|
|
3275
|
-
cache.lids.forEach(identifier => {
|
|
3276
|
-
this.unloadRecord(identifier);
|
|
3277
|
-
});
|
|
3278
|
-
} else {
|
|
3279
|
-
const typeCache = cache.types;
|
|
3280
|
-
let identifiers = typeCache[type]?.lid;
|
|
3281
|
-
// const rds = this.__instances.resourceCache;
|
|
3282
|
-
if (identifiers) {
|
|
3283
|
-
identifiers.forEach(identifier => {
|
|
3284
|
-
// if (rds.has(identifier)) {
|
|
3285
|
-
this.unloadRecord(identifier);
|
|
3286
|
-
// }
|
|
3287
|
-
// TODO we don't remove the identifier, should we?
|
|
3288
|
-
});
|
|
3289
|
-
}
|
|
3290
|
-
}
|
|
3291
|
-
}
|
|
3292
|
-
|
|
3293
|
-
// TODO this should move into something coordinating operations
|
|
3294
|
-
setRecordId(identifier, id) {
|
|
3295
|
-
const {
|
|
3296
|
-
type,
|
|
3297
|
-
lid
|
|
3298
|
-
} = identifier;
|
|
3299
|
-
let oldId = identifier.id;
|
|
3300
|
-
|
|
3301
|
-
// ID absolutely can't be missing if the oldID is empty (missing Id in response for a new record)
|
|
3302
|
-
assert(`'${type}' was saved to the server, but the response does not have an id and your record does not either.`, !(id === null && oldId === null));
|
|
3303
|
-
|
|
3304
|
-
// ID absolutely can't be different than oldID if oldID is not null
|
|
3305
|
-
// TODO this assertion and restriction may not strictly be needed in the identifiers world
|
|
3306
|
-
assert(`Cannot update the id for '${type}:${lid}' from '${String(oldId)}' to '${id}'.`, !(oldId !== null && id !== oldId));
|
|
3307
|
-
|
|
3308
|
-
// ID can be null if oldID is not null (altered ID in response for a record)
|
|
3309
|
-
// however, this is more than likely a developer error.
|
|
3310
|
-
if (oldId !== null && id === null) {
|
|
3311
|
-
warn(`Your ${type} record was saved to the server, but the response does not have an id.`, !(oldId !== null && id === null));
|
|
3312
|
-
return;
|
|
3313
|
-
}
|
|
3314
|
-
if (macroCondition(getOwnConfig().debug.LOG_INSTANCE_CACHE)) {
|
|
3315
|
-
// eslint-disable-next-line no-console
|
|
3316
|
-
console.log(`InstanceCache: updating id to '${id}' for record ${String(identifier)}`);
|
|
3317
|
-
}
|
|
3318
|
-
let existingIdentifier = this.store.identifierCache.peekRecordIdentifier({
|
|
3319
|
-
type,
|
|
3320
|
-
id
|
|
3321
|
-
});
|
|
3322
|
-
assert(`'${type}' was saved to the server, but the response returned the new id '${id}', which has already been used with another record.'`, !existingIdentifier || existingIdentifier === identifier);
|
|
3323
|
-
if (identifier.id === null) {
|
|
3324
|
-
// TODO potentially this needs to handle merged result
|
|
3325
|
-
this.store.identifierCache.updateRecordIdentifier(identifier, {
|
|
3326
|
-
type,
|
|
3327
|
-
id
|
|
3328
|
-
});
|
|
3329
|
-
}
|
|
3330
|
-
|
|
3331
|
-
// TODO update resource cache if needed ?
|
|
3332
|
-
// TODO handle consequences of identifier merge for notifications
|
|
3333
|
-
this.store.notifications.notify(identifier, 'identity');
|
|
3334
|
-
}
|
|
3335
|
-
|
|
3336
|
-
// TODO ths should be wrapped in a deprecation flag since cache.put
|
|
3337
|
-
// handles this the rest of the time
|
|
3338
|
-
loadData(data) {
|
|
3339
|
-
let modelName = data.type;
|
|
3340
|
-
assert(`You must include an 'id' for ${modelName} in an object passed to 'push'`, data.id !== null && data.id !== undefined && data.id !== '');
|
|
3341
|
-
assert(`You tried to push data with a type '${modelName}' but no model could be found with that name.`, this.store.getSchemaDefinitionService().doesTypeExist(modelName));
|
|
3342
|
-
const resource = constructResource(normalizeModelName$1(data.type), ensureStringId(data.id), coerceId(data.lid));
|
|
3343
|
-
let identifier = this.store.identifierCache.peekRecordIdentifier(resource);
|
|
3344
|
-
let isUpdate = false;
|
|
3345
|
-
|
|
3346
|
-
// store.push will be from empty
|
|
3347
|
-
// findRecord will be from root.loading
|
|
3348
|
-
// this cannot be loading state if we do not already have an identifier
|
|
3349
|
-
// all else will be updates
|
|
3350
|
-
if (identifier) {
|
|
3351
|
-
const isLoading = _isLoading(this, identifier) || !this.recordIsLoaded(identifier);
|
|
3352
|
-
isUpdate = !_isEmpty(this, identifier) && !isLoading;
|
|
3353
|
-
|
|
3354
|
-
// exclude store.push (root.empty) case
|
|
3355
|
-
if (isUpdate || isLoading) {
|
|
3356
|
-
identifier = this.store.identifierCache.updateRecordIdentifier(identifier, data);
|
|
3357
|
-
}
|
|
3358
|
-
} else {
|
|
3359
|
-
identifier = this.store.identifierCache.getOrCreateRecordIdentifier(data);
|
|
3360
|
-
}
|
|
3361
|
-
const cache = this.getResourceCache(identifier);
|
|
3362
|
-
const hasRecord = this.__instances.record.has(identifier);
|
|
3363
|
-
cache.upsert(identifier, data, hasRecord);
|
|
3364
|
-
return identifier;
|
|
2246
|
+
/**
|
|
2247
|
+
* Merge a fork back into a parent Cache.
|
|
2248
|
+
*
|
|
2249
|
+
* Applications should typically not call this method themselves,
|
|
2250
|
+
* preferring instead to merge at the Store level, which will
|
|
2251
|
+
* utilize this method to merge the caches.
|
|
2252
|
+
*
|
|
2253
|
+
* @method merge
|
|
2254
|
+
* @param {Cache} cache
|
|
2255
|
+
* @public
|
|
2256
|
+
* @returns Promise<void>
|
|
2257
|
+
*/
|
|
2258
|
+
merge(cache) {
|
|
2259
|
+
return _classPrivateFieldBase(this, _cache)[_cache].merge(cache);
|
|
3365
2260
|
}
|
|
3366
|
-
}
|
|
3367
|
-
function _resourceIsFullDeleted(identifier, cache) {
|
|
3368
|
-
return cache.isDeletionCommitted(identifier) || cache.isNew(identifier) && cache.isDeleted(identifier);
|
|
3369
|
-
}
|
|
3370
|
-
function resourceIsFullyDeleted(instanceCache, identifier) {
|
|
3371
|
-
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? instanceCache.__instances.resourceCache.get(identifier) : instanceCache.cache;
|
|
3372
|
-
return !cache || _resourceIsFullDeleted(identifier, cache);
|
|
3373
|
-
}
|
|
3374
|
-
|
|
3375
|
-
/*
|
|
3376
|
-
When a find request is triggered on the store, the user can optionally pass in
|
|
3377
|
-
attributes and relationships to be preloaded. These are meant to behave as if they
|
|
3378
|
-
came back from the server, except the user obtained them out of band and is informing
|
|
3379
|
-
the store of their existence. The most common use case is for supporting client side
|
|
3380
|
-
nested URLs, such as `/posts/1/comments/2` so the user can do
|
|
3381
|
-
`store.findRecord('comment', 2, { preload: { post: 1 } })` without having to fetch the post.
|
|
3382
|
-
|
|
3383
|
-
Preloaded data can be attributes and relationships passed in either as IDs or as actual
|
|
3384
|
-
models.
|
|
3385
|
-
*/
|
|
3386
2261
|
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
2262
|
+
/**
|
|
2263
|
+
* Generate the list of changes applied to all
|
|
2264
|
+
* record in the store.
|
|
2265
|
+
*
|
|
2266
|
+
* Each individual resource or document that has
|
|
2267
|
+
* been mutated should be described as an individual
|
|
2268
|
+
* `Change` entry in the returned array.
|
|
2269
|
+
*
|
|
2270
|
+
* A `Change` is described by an object containing up to
|
|
2271
|
+
* three properties: (1) the `identifier` of the entity that
|
|
2272
|
+
* changed; (2) the `op` code of that change being one of
|
|
2273
|
+
* `upsert` or `remove`, and if the op is `upsert` a `patch`
|
|
2274
|
+
* containing the data to merge into the cache for the given
|
|
2275
|
+
* entity.
|
|
2276
|
+
*
|
|
2277
|
+
* This `patch` is opaque to the Store but should be understood
|
|
2278
|
+
* by the Cache and may expect to be utilized by an Adapter
|
|
2279
|
+
* when generating data during a `save` operation.
|
|
2280
|
+
*
|
|
2281
|
+
* It is generally recommended that the `patch` contain only
|
|
2282
|
+
* the updated state, ignoring fields that are unchanged
|
|
2283
|
+
*
|
|
2284
|
+
* ```ts
|
|
2285
|
+
* interface Change {
|
|
2286
|
+
* identifier: StableRecordIdentifier | StableDocumentIdentifier;
|
|
2287
|
+
* op: 'upsert' | 'remove';
|
|
2288
|
+
* patch?: unknown;
|
|
2289
|
+
* }
|
|
2290
|
+
* ```
|
|
2291
|
+
*
|
|
2292
|
+
* @method diff
|
|
2293
|
+
* @public
|
|
2294
|
+
*/
|
|
2295
|
+
diff() {
|
|
2296
|
+
return _classPrivateFieldBase(this, _cache)[_cache].diff();
|
|
3421
2297
|
}
|
|
3422
|
-
assert('You should not pass in an array to set a belongsTo property on a record', !Array.isArray(preloadValue));
|
|
3423
|
-
return {
|
|
3424
|
-
data: preloadValue ? _convertPreloadRelationshipToJSON(preloadValue, relatedType) : null
|
|
3425
|
-
};
|
|
3426
|
-
}
|
|
3427
2298
|
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
findRecord('user', '1', { preload: { friends: [record] }});
|
|
3431
|
-
*/
|
|
3432
|
-
function _convertPreloadRelationshipToJSON(value, type) {
|
|
3433
|
-
if (typeof value === 'string' || typeof value === 'number') {
|
|
3434
|
-
return {
|
|
3435
|
-
type,
|
|
3436
|
-
id: value
|
|
3437
|
-
};
|
|
3438
|
-
}
|
|
3439
|
-
// TODO if not a record instance assert it's an identifier
|
|
3440
|
-
// and allow identifiers to be used
|
|
3441
|
-
return recordIdentifierFor(value);
|
|
3442
|
-
}
|
|
3443
|
-
function _isEmpty(instanceCache, identifier) {
|
|
3444
|
-
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? instanceCache.__instances.resourceCache.get(identifier) : instanceCache.cache;
|
|
3445
|
-
if (!cache) {
|
|
3446
|
-
return true;
|
|
3447
|
-
}
|
|
3448
|
-
const isNew = cache.isNew(identifier);
|
|
3449
|
-
const isDeleted = cache.isDeleted(identifier);
|
|
3450
|
-
const isEmpty = cache.isEmpty(identifier);
|
|
3451
|
-
return (!isNew || isDeleted) && isEmpty;
|
|
3452
|
-
}
|
|
3453
|
-
function _isLoading(cache, identifier) {
|
|
3454
|
-
const req = cache.store.getRequestStateService();
|
|
3455
|
-
// const fulfilled = req.getLastRequestForRecord(identifier);
|
|
3456
|
-
const isLoaded = cache.recordIsLoaded(identifier);
|
|
3457
|
-
return !isLoaded &&
|
|
3458
|
-
// fulfilled === null &&
|
|
3459
|
-
req.getPendingRequestsForRecord(identifier).some(req => req.type === 'query');
|
|
3460
|
-
}
|
|
3461
|
-
function _clearCaches() {
|
|
3462
|
-
RecordCache.clear();
|
|
3463
|
-
StoreMap.clear();
|
|
3464
|
-
CacheForIdentifierCache.clear();
|
|
3465
|
-
}
|
|
3466
|
-
let _modelForMixin;
|
|
3467
|
-
if (macroCondition(getOwnConfig().packages.HAS_MODEL_PACKAGE)) {
|
|
3468
|
-
let _found;
|
|
3469
|
-
_modelForMixin = function () {
|
|
3470
|
-
if (!_found) {
|
|
3471
|
-
_found = importSync('@ember-data/model/-private')._modelForMixin;
|
|
3472
|
-
}
|
|
3473
|
-
return _found(...arguments);
|
|
3474
|
-
};
|
|
3475
|
-
}
|
|
3476
|
-
class DSModelSchemaDefinitionService {
|
|
3477
|
-
constructor(store) {
|
|
3478
|
-
this.store = store;
|
|
3479
|
-
this._relationshipsDefCache = Object.create(null);
|
|
3480
|
-
this._attributesDefCache = Object.create(null);
|
|
3481
|
-
}
|
|
2299
|
+
// SSR Support
|
|
2300
|
+
// ===========
|
|
3482
2301
|
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
available: '4.5'
|
|
3495
|
-
}
|
|
3496
|
-
});
|
|
3497
|
-
modelName = identifier;
|
|
3498
|
-
} else {
|
|
3499
|
-
modelName = identifier.type;
|
|
3500
|
-
}
|
|
3501
|
-
} else {
|
|
3502
|
-
modelName = identifier.type;
|
|
3503
|
-
}
|
|
3504
|
-
attributes = this._attributesDefCache[modelName];
|
|
3505
|
-
if (attributes === undefined) {
|
|
3506
|
-
let modelClass = this.store.modelFor(modelName);
|
|
3507
|
-
let attributeMap = modelClass.attributes;
|
|
3508
|
-
attributes = Object.create(null);
|
|
3509
|
-
attributeMap.forEach((meta, name) => attributes[name] = meta);
|
|
3510
|
-
this._attributesDefCache[modelName] = attributes;
|
|
3511
|
-
}
|
|
3512
|
-
return attributes;
|
|
2302
|
+
/**
|
|
2303
|
+
* Serialize the entire contents of the Cache into a Stream
|
|
2304
|
+
* which may be fed back into a new instance of the same Cache
|
|
2305
|
+
* via `cache.hydrate`.
|
|
2306
|
+
*
|
|
2307
|
+
* @method dump
|
|
2308
|
+
* @returns {Promise<ReadableStream>}
|
|
2309
|
+
* @public
|
|
2310
|
+
*/
|
|
2311
|
+
dump() {
|
|
2312
|
+
return _classPrivateFieldBase(this, _cache)[_cache].dump();
|
|
3513
2313
|
}
|
|
3514
2314
|
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
modelName = identifier.type;
|
|
3535
|
-
}
|
|
3536
|
-
relationships = this._relationshipsDefCache[modelName];
|
|
3537
|
-
if (relationships === undefined) {
|
|
3538
|
-
let modelClass = this.store.modelFor(modelName);
|
|
3539
|
-
relationships = modelClass.relationshipsObject || null;
|
|
3540
|
-
this._relationshipsDefCache[modelName] = relationships;
|
|
3541
|
-
}
|
|
3542
|
-
return relationships;
|
|
3543
|
-
}
|
|
3544
|
-
doesTypeExist(modelName) {
|
|
3545
|
-
let normalizedModelName = normalizeModelName$1(modelName);
|
|
3546
|
-
let factory = getModelFactory(this.store, this.store._modelFactoryCache, normalizedModelName);
|
|
3547
|
-
return factory !== null;
|
|
3548
|
-
}
|
|
3549
|
-
}
|
|
3550
|
-
function getModelFactory(store, cache, normalizedModelName) {
|
|
3551
|
-
let factory = cache[normalizedModelName];
|
|
3552
|
-
if (!factory) {
|
|
3553
|
-
let owner = getOwner(store);
|
|
3554
|
-
factory = owner.factoryFor(`model:${normalizedModelName}`);
|
|
3555
|
-
if (macroCondition(getOwnConfig().packages.HAS_MODEL_PACKAGE)) {
|
|
3556
|
-
if (!factory) {
|
|
3557
|
-
//Support looking up mixins as base types for polymorphic relationships
|
|
3558
|
-
factory = _modelForMixin(store, normalizedModelName);
|
|
3559
|
-
}
|
|
3560
|
-
}
|
|
3561
|
-
if (!factory) {
|
|
3562
|
-
// we don't cache misses in case someone wants to register a missing model
|
|
3563
|
-
return null;
|
|
3564
|
-
}
|
|
3565
|
-
let klass = factory.class;
|
|
3566
|
-
if (klass.isModel) {
|
|
3567
|
-
let hasOwnModelNameSet = klass.modelName && Object.prototype.hasOwnProperty.call(klass, 'modelName');
|
|
3568
|
-
if (!hasOwnModelNameSet) {
|
|
3569
|
-
Object.defineProperty(klass, 'modelName', {
|
|
3570
|
-
value: normalizedModelName
|
|
3571
|
-
});
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
cache[normalizedModelName] = factory;
|
|
2315
|
+
/**
|
|
2316
|
+
* hydrate a Cache from a Stream with content previously serialized
|
|
2317
|
+
* from another instance of the same Cache, resolving when hydration
|
|
2318
|
+
* is complete.
|
|
2319
|
+
*
|
|
2320
|
+
* This method should expect to be called both in the context of restoring
|
|
2321
|
+
* the Cache during application rehydration after SSR **AND** at unknown
|
|
2322
|
+
* times during the lifetime of an already booted application when it is
|
|
2323
|
+
* desired to bulk-load additional information into the cache. This latter
|
|
2324
|
+
* behavior supports optimizing pre/fetching of data for route transitions
|
|
2325
|
+
* via data-only SSR modes.
|
|
2326
|
+
*
|
|
2327
|
+
* @method hydrate
|
|
2328
|
+
* @param {ReadableStream} stream
|
|
2329
|
+
* @returns {Promise<void>}
|
|
2330
|
+
* @public
|
|
2331
|
+
*/
|
|
2332
|
+
hydrate(stream) {
|
|
2333
|
+
return _classPrivateFieldBase(this, _cache)[_cache].hydrate(stream);
|
|
3575
2334
|
}
|
|
3576
|
-
return factory;
|
|
3577
|
-
}
|
|
3578
2335
|
|
|
3579
|
-
//
|
|
3580
|
-
//
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
map.set(i, hash[i]);
|
|
3599
|
-
}
|
|
2336
|
+
// Cache
|
|
2337
|
+
// =====
|
|
2338
|
+
|
|
2339
|
+
// Resource Support
|
|
2340
|
+
// ================
|
|
2341
|
+
|
|
2342
|
+
/**
|
|
2343
|
+
* [LIFECYLCE] Signal to the cache that a new record has been instantiated on the client
|
|
2344
|
+
*
|
|
2345
|
+
* It returns properties from options that should be set on the record during the create
|
|
2346
|
+
* process. This return value behavior is deprecated.
|
|
2347
|
+
*
|
|
2348
|
+
* @method clientDidCreate
|
|
2349
|
+
* @public
|
|
2350
|
+
* @param identifier
|
|
2351
|
+
* @param options
|
|
2352
|
+
*/
|
|
2353
|
+
clientDidCreate(identifier, options) {
|
|
2354
|
+
return _classPrivateFieldBase(this, _cache)[_cache].clientDidCreate(identifier, options);
|
|
3600
2355
|
}
|
|
3601
|
-
return map;
|
|
3602
|
-
}
|
|
3603
2356
|
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
2357
|
+
/**
|
|
2358
|
+
* [LIFECYCLE] Signals to the cache that a resource
|
|
2359
|
+
* will be part of a save transaction.
|
|
2360
|
+
*
|
|
2361
|
+
* @method willCommit
|
|
2362
|
+
* @public
|
|
2363
|
+
* @param identifier
|
|
2364
|
+
*/
|
|
2365
|
+
willCommit(identifier) {
|
|
2366
|
+
_classPrivateFieldBase(this, _cache)[_cache].willCommit(identifier);
|
|
3609
2367
|
}
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
2368
|
+
|
|
2369
|
+
/**
|
|
2370
|
+
* [LIFECYCLE] Signals to the cache that a resource
|
|
2371
|
+
* was successfully updated as part of a save transaction.
|
|
2372
|
+
*
|
|
2373
|
+
* @method didCommit
|
|
2374
|
+
* @public
|
|
2375
|
+
* @param identifier
|
|
2376
|
+
* @param data
|
|
2377
|
+
*/
|
|
2378
|
+
didCommit(identifier, data) {
|
|
2379
|
+
_classPrivateFieldBase(this, _cache)[_cache].didCommit(identifier, data);
|
|
3621
2380
|
}
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
2381
|
+
|
|
2382
|
+
/**
|
|
2383
|
+
* [LIFECYCLE] Signals to the cache that a resource
|
|
2384
|
+
* was update via a save transaction failed.
|
|
2385
|
+
*
|
|
2386
|
+
* @method commitWasRejected
|
|
2387
|
+
* @public
|
|
2388
|
+
* @param identifier
|
|
2389
|
+
* @param errors
|
|
2390
|
+
*/
|
|
2391
|
+
commitWasRejected(identifier, errors) {
|
|
2392
|
+
_classPrivateFieldBase(this, _cache)[_cache].commitWasRejected(identifier, errors);
|
|
3627
2393
|
}
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
2394
|
+
|
|
2395
|
+
/**
|
|
2396
|
+
* [LIFECYCLE] Signals to the cache that all data for a resource
|
|
2397
|
+
* should be cleared.
|
|
2398
|
+
*
|
|
2399
|
+
* @method unloadRecord
|
|
2400
|
+
* @public
|
|
2401
|
+
* @param identifier
|
|
2402
|
+
*/
|
|
2403
|
+
unloadRecord(identifier) {
|
|
2404
|
+
_classPrivateFieldBase(this, _cache)[_cache].unloadRecord(identifier);
|
|
3633
2405
|
}
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
2406
|
+
|
|
2407
|
+
// Granular Resource Data APIs
|
|
2408
|
+
// ===========================
|
|
2409
|
+
|
|
2410
|
+
/**
|
|
2411
|
+
* Retrieve the data for an attribute from the cache
|
|
2412
|
+
*
|
|
2413
|
+
* @method getAttr
|
|
2414
|
+
* @public
|
|
2415
|
+
* @param identifier
|
|
2416
|
+
* @param propertyName
|
|
2417
|
+
* @returns {unknown}
|
|
2418
|
+
*/
|
|
2419
|
+
getAttr(identifier, propertyName) {
|
|
2420
|
+
return _classPrivateFieldBase(this, _cache)[_cache].getAttr(identifier, propertyName);
|
|
3641
2421
|
}
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
2422
|
+
|
|
2423
|
+
/**
|
|
2424
|
+
* Mutate the data for an attribute in the cache
|
|
2425
|
+
*
|
|
2426
|
+
* @method setAttr
|
|
2427
|
+
* @public
|
|
2428
|
+
* @param identifier
|
|
2429
|
+
* @param propertyName
|
|
2430
|
+
* @param value
|
|
2431
|
+
*/
|
|
2432
|
+
setAttr(identifier, propertyName, value) {
|
|
2433
|
+
_classPrivateFieldBase(this, _cache)[_cache].setAttr(identifier, propertyName, value);
|
|
3649
2434
|
}
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
2435
|
+
|
|
2436
|
+
/**
|
|
2437
|
+
* Query the cache for the changed attributes of a resource.
|
|
2438
|
+
*
|
|
2439
|
+
* @method changedAttrs
|
|
2440
|
+
* @public
|
|
2441
|
+
* @param identifier
|
|
2442
|
+
* @returns
|
|
2443
|
+
*/
|
|
2444
|
+
changedAttrs(identifier) {
|
|
2445
|
+
return _classPrivateFieldBase(this, _cache)[_cache].changedAttrs(identifier);
|
|
3659
2446
|
}
|
|
3660
|
-
}
|
|
3661
|
-
const PromiseArrayProxy = ArrayProxy.extend(PromiseProxyMixin);
|
|
3662
|
-
const PromiseObjectProxy = ObjectProxy.extend(PromiseProxyMixin);
|
|
3663
|
-
var _dec, _class$1, _descriptor$1;
|
|
3664
2447
|
|
|
3665
|
-
/**
|
|
3666
|
-
|
|
3667
|
-
|
|
2448
|
+
/**
|
|
2449
|
+
* Query the cache for whether any mutated attributes exist
|
|
2450
|
+
*
|
|
2451
|
+
* @method hasChangedAttrs
|
|
2452
|
+
* @public
|
|
2453
|
+
* @param identifier
|
|
2454
|
+
* @returns {boolean}
|
|
2455
|
+
*/
|
|
2456
|
+
hasChangedAttrs(identifier) {
|
|
2457
|
+
return _classPrivateFieldBase(this, _cache)[_cache].hasChangedAttrs(identifier);
|
|
2458
|
+
}
|
|
3668
2459
|
|
|
3669
|
-
/**
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
2460
|
+
/**
|
|
2461
|
+
* Tell the cache to discard any uncommitted mutations to attributes
|
|
2462
|
+
*
|
|
2463
|
+
* @method rollbackAttrs
|
|
2464
|
+
* @public
|
|
2465
|
+
* @param identifier
|
|
2466
|
+
* @returns the names of attributes that were restored
|
|
2467
|
+
*/
|
|
2468
|
+
rollbackAttrs(identifier) {
|
|
2469
|
+
return _classPrivateFieldBase(this, _cache)[_cache].rollbackAttrs(identifier);
|
|
2470
|
+
}
|
|
3675
2471
|
|
|
3676
|
-
|
|
2472
|
+
// Relationships
|
|
2473
|
+
// =============
|
|
3677
2474
|
|
|
3678
|
-
|
|
3679
|
-
|
|
2475
|
+
/**
|
|
2476
|
+
* Query the cache for the current state of a relationship property
|
|
2477
|
+
*
|
|
2478
|
+
* @method getRelationship
|
|
2479
|
+
* @public
|
|
2480
|
+
* @param identifier
|
|
2481
|
+
* @param propertyName
|
|
2482
|
+
* @returns resource relationship object
|
|
2483
|
+
*/
|
|
2484
|
+
getRelationship(identifier, propertyName) {
|
|
2485
|
+
return _classPrivateFieldBase(this, _cache)[_cache].getRelationship(identifier, propertyName);
|
|
2486
|
+
}
|
|
3680
2487
|
|
|
3681
|
-
|
|
2488
|
+
// Resource State
|
|
2489
|
+
// ===============
|
|
3682
2490
|
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
2491
|
+
/**
|
|
2492
|
+
* Update the cache state for the given resource to be marked as locally deleted,
|
|
2493
|
+
* or remove such a mark.
|
|
2494
|
+
*
|
|
2495
|
+
* @method setIsDeleted
|
|
2496
|
+
* @public
|
|
2497
|
+
* @param identifier
|
|
2498
|
+
* @param isDeleted
|
|
2499
|
+
*/
|
|
2500
|
+
setIsDeleted(identifier, isDeleted) {
|
|
2501
|
+
_classPrivateFieldBase(this, _cache)[_cache].setIsDeleted(identifier, isDeleted);
|
|
2502
|
+
}
|
|
3687
2503
|
|
|
3688
|
-
|
|
2504
|
+
/**
|
|
2505
|
+
* Query the cache for any validation errors applicable to the given resource.
|
|
2506
|
+
*
|
|
2507
|
+
* @method getErrors
|
|
2508
|
+
* @public
|
|
2509
|
+
* @param identifier
|
|
2510
|
+
* @returns
|
|
2511
|
+
*/
|
|
2512
|
+
getErrors(identifier) {
|
|
2513
|
+
return _classPrivateFieldBase(this, _cache)[_cache].getErrors(identifier);
|
|
2514
|
+
}
|
|
3689
2515
|
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
2516
|
+
/**
|
|
2517
|
+
* Query the cache for whether a given resource has any available data
|
|
2518
|
+
*
|
|
2519
|
+
* @method isEmpty
|
|
2520
|
+
* @public
|
|
2521
|
+
* @param identifier
|
|
2522
|
+
* @returns {boolean}
|
|
2523
|
+
*/
|
|
2524
|
+
isEmpty(identifier) {
|
|
2525
|
+
return _classPrivateFieldBase(this, _cache)[_cache].isEmpty(identifier);
|
|
2526
|
+
}
|
|
3694
2527
|
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
2528
|
+
/**
|
|
2529
|
+
* Query the cache for whether a given resource was created locally and not
|
|
2530
|
+
* yet persisted.
|
|
2531
|
+
*
|
|
2532
|
+
* @method isNew
|
|
2533
|
+
* @public
|
|
2534
|
+
* @param identifier
|
|
2535
|
+
* @returns {boolean}
|
|
2536
|
+
*/
|
|
2537
|
+
isNew(identifier) {
|
|
2538
|
+
return _classPrivateFieldBase(this, _cache)[_cache].isNew(identifier);
|
|
3704
2539
|
}
|
|
3705
|
-
}, _descriptor$1 = _applyDecoratedDescriptor(_class$1.prototype, "meta", [_dec], {
|
|
3706
|
-
configurable: true,
|
|
3707
|
-
enumerable: true,
|
|
3708
|
-
writable: true,
|
|
3709
|
-
initializer: null
|
|
3710
|
-
}), _class$1));
|
|
3711
|
-
function _promiseObject(promise) {
|
|
3712
|
-
return PromiseObjectProxy.create({
|
|
3713
|
-
promise
|
|
3714
|
-
});
|
|
3715
|
-
}
|
|
3716
|
-
function _promiseArray(promise) {
|
|
3717
|
-
return PromiseArray.create({
|
|
3718
|
-
promise
|
|
3719
|
-
});
|
|
3720
|
-
}
|
|
3721
2540
|
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
if (ALLOWABLE_PROPS.includes(prop)) {
|
|
3738
|
-
return target[prop];
|
|
3739
|
-
}
|
|
3740
|
-
if (!ALLOWABLE_METHODS.includes(prop)) {
|
|
3741
|
-
deprecate(`Accessing ${prop} on this PromiseArray is deprecated. The return type is being changed from PromiseArray to a Promise. The only available methods to access on this promise are .then, .catch and .finally`, false, {
|
|
3742
|
-
id: 'ember-data:deprecate-promise-proxies',
|
|
3743
|
-
until: '5.0',
|
|
3744
|
-
for: '@ember-data/store',
|
|
3745
|
-
since: {
|
|
3746
|
-
available: '4.7',
|
|
3747
|
-
enabled: '4.7'
|
|
3748
|
-
}
|
|
3749
|
-
});
|
|
3750
|
-
}
|
|
3751
|
-
const value = target[prop];
|
|
3752
|
-
if (value && typeof value === 'function' && typeof value.bind === 'function') {
|
|
3753
|
-
return value.bind(target);
|
|
3754
|
-
}
|
|
3755
|
-
if (PROXIED_ARRAY_PROPS.includes(prop)) {
|
|
3756
|
-
return value;
|
|
3757
|
-
}
|
|
3758
|
-
return undefined;
|
|
3759
|
-
}
|
|
3760
|
-
};
|
|
3761
|
-
return new Proxy(promiseObjectProxy, handler);
|
|
3762
|
-
}
|
|
3763
|
-
const ProxySymbolString = String(Symbol.for('PROXY_CONTENT'));
|
|
3764
|
-
function promiseObject(promise) {
|
|
3765
|
-
const promiseObjectProxy = _promiseObject(promise);
|
|
3766
|
-
if (macroCondition(!getOwnConfig().env.DEBUG)) {
|
|
3767
|
-
return promiseObjectProxy;
|
|
3768
|
-
}
|
|
3769
|
-
const handler = {
|
|
3770
|
-
get(target, prop, receiver) {
|
|
3771
|
-
if (typeof prop === 'symbol') {
|
|
3772
|
-
if (String(prop) === ProxySymbolString) {
|
|
3773
|
-
return;
|
|
3774
|
-
}
|
|
3775
|
-
return Reflect.get(target, prop, receiver);
|
|
3776
|
-
}
|
|
3777
|
-
if (prop === 'constructor') {
|
|
3778
|
-
return target.constructor;
|
|
3779
|
-
}
|
|
3780
|
-
if (ALLOWABLE_PROPS.includes(prop)) {
|
|
3781
|
-
return target[prop];
|
|
3782
|
-
}
|
|
3783
|
-
if (!ALLOWABLE_METHODS.includes(prop)) {
|
|
3784
|
-
deprecate(`Accessing ${prop} on this PromiseObject is deprecated. The return type is being changed from PromiseObject to a Promise. The only available methods to access on this promise are .then, .catch and .finally`, false, {
|
|
3785
|
-
id: 'ember-data:deprecate-promise-proxies',
|
|
3786
|
-
until: '5.0',
|
|
3787
|
-
for: '@ember-data/store',
|
|
3788
|
-
since: {
|
|
3789
|
-
available: '4.7',
|
|
3790
|
-
enabled: '4.7'
|
|
3791
|
-
}
|
|
3792
|
-
});
|
|
3793
|
-
} else {
|
|
3794
|
-
return target[prop].bind(target);
|
|
3795
|
-
}
|
|
3796
|
-
if (PROXIED_OBJECT_PROPS.includes(prop)) {
|
|
3797
|
-
return target[prop];
|
|
3798
|
-
}
|
|
3799
|
-
const value = get(target, prop);
|
|
3800
|
-
if (value && typeof value === 'function' && typeof value.bind === 'function') {
|
|
3801
|
-
return value.bind(receiver);
|
|
3802
|
-
}
|
|
3803
|
-
return undefined;
|
|
3804
|
-
}
|
|
3805
|
-
};
|
|
3806
|
-
return new Proxy(promiseObjectProxy, handler);
|
|
2541
|
+
/**
|
|
2542
|
+
* Query the cache for whether a given resource is marked as deleted (but not
|
|
2543
|
+
* necessarily persisted yet).
|
|
2544
|
+
*
|
|
2545
|
+
* @method isDeleted
|
|
2546
|
+
* @public
|
|
2547
|
+
* @param identifier
|
|
2548
|
+
* @returns {boolean}
|
|
2549
|
+
*/
|
|
2550
|
+
isDeleted(identifier) {
|
|
2551
|
+
return _classPrivateFieldBase(this, _cache)[_cache].isDeleted(identifier);
|
|
2552
|
+
}
|
|
2553
|
+
isDeletionCommitted(identifier) {
|
|
2554
|
+
return _classPrivateFieldBase(this, _cache)[_cache].isDeletionCommitted(identifier);
|
|
2555
|
+
}
|
|
3807
2556
|
}
|
|
3808
2557
|
var _class, _descriptor, _class3, _descriptor2;
|
|
3809
2558
|
const ARRAY_GETTER_METHODS = new Set([Symbol.iterator, 'concat', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'flat', 'flatMap', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'map', 'reduce', 'reduceRight', 'slice', 'some', 'values']);
|
|
@@ -3853,17 +2602,6 @@ let Tag = (_class = class Tag {
|
|
|
3853
2602
|
return null;
|
|
3854
2603
|
}
|
|
3855
2604
|
}), _class);
|
|
3856
|
-
function deprecateArrayLike(className, fnName, replName) {
|
|
3857
|
-
deprecate(`The \`${fnName}\` method on the class ${className} is deprecated. Use the native array method \`${replName}\` instead.`, false, {
|
|
3858
|
-
id: 'ember-data:deprecate-array-like',
|
|
3859
|
-
until: '5.0',
|
|
3860
|
-
since: {
|
|
3861
|
-
enabled: '4.7',
|
|
3862
|
-
available: '4.7'
|
|
3863
|
-
},
|
|
3864
|
-
for: 'ember-data'
|
|
3865
|
-
});
|
|
3866
|
-
}
|
|
3867
2605
|
function safeForEach(instance, arr, store, callback, target) {
|
|
3868
2606
|
if (target === undefined) {
|
|
3869
2607
|
target = null;
|
|
@@ -3915,14 +2653,6 @@ let IdentifierArray = (_class3 = class IdentifierArray {
|
|
|
3915
2653
|
notifyArray(this);
|
|
3916
2654
|
}
|
|
3917
2655
|
|
|
3918
|
-
/**
|
|
3919
|
-
The modelClass represented by this record array.
|
|
3920
|
-
@property type
|
|
3921
|
-
@public
|
|
3922
|
-
@deprecated
|
|
3923
|
-
@type {subclass of Model}
|
|
3924
|
-
*/
|
|
3925
|
-
|
|
3926
2656
|
/**
|
|
3927
2657
|
The store that created this record array.
|
|
3928
2658
|
@property store
|
|
@@ -4051,15 +2781,6 @@ let IdentifierArray = (_class3 = class IdentifierArray {
|
|
|
4051
2781
|
return fn;
|
|
4052
2782
|
}
|
|
4053
2783
|
if (prop in self) {
|
|
4054
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_ARRAY_LIKE)) {
|
|
4055
|
-
if (prop === 'firstObject') {
|
|
4056
|
-
deprecateArrayLike(self.DEPRECATED_CLASS_NAME, prop, '[0]');
|
|
4057
|
-
return receiver[0];
|
|
4058
|
-
} else if (prop === 'lastObject') {
|
|
4059
|
-
deprecateArrayLike(self.DEPRECATED_CLASS_NAME, prop, 'at(-1)');
|
|
4060
|
-
return receiver[receiver.length - 1];
|
|
4061
|
-
}
|
|
4062
|
-
}
|
|
4063
2784
|
if (prop === NOTIFY || prop === IDENTIFIER_ARRAY_TAG || prop === SOURCE) {
|
|
4064
2785
|
return self[prop];
|
|
4065
2786
|
}
|
|
@@ -4135,25 +2856,7 @@ let IdentifierArray = (_class3 = class IdentifierArray {
|
|
|
4135
2856
|
return IdentifierArray.prototype;
|
|
4136
2857
|
}
|
|
4137
2858
|
});
|
|
4138
|
-
if (macroCondition(getOwnConfig().
|
|
4139
|
-
const meta = Ember.meta(this);
|
|
4140
|
-
meta.hasMixin = mixin => {
|
|
4141
|
-
deprecate(`Do not call A() on EmberData RecordArrays`, false, {
|
|
4142
|
-
id: 'ember-data:no-a-with-array-like',
|
|
4143
|
-
until: '5.0',
|
|
4144
|
-
since: {
|
|
4145
|
-
enabled: '4.7',
|
|
4146
|
-
available: '4.7'
|
|
4147
|
-
},
|
|
4148
|
-
for: 'ember-data'
|
|
4149
|
-
});
|
|
4150
|
-
// @ts-expect-error ArrayMixin is more than a type
|
|
4151
|
-
if (mixin === NativeArray || mixin === ArrayMixin) {
|
|
4152
|
-
return true;
|
|
4153
|
-
}
|
|
4154
|
-
return false;
|
|
4155
|
-
};
|
|
4156
|
-
} else if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
2859
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
4157
2860
|
const meta = Ember.meta(this);
|
|
4158
2861
|
meta.hasMixin = mixin => {
|
|
4159
2862
|
assert(`Do not call A() on EmberData RecordArrays`);
|
|
@@ -4219,13 +2922,10 @@ let IdentifierArray = (_class3 = class IdentifierArray {
|
|
|
4219
2922
|
```
|
|
4220
2923
|
@method save
|
|
4221
2924
|
@public
|
|
4222
|
-
@return {
|
|
2925
|
+
@return {Promise<IdentifierArray>} promise
|
|
4223
2926
|
*/
|
|
4224
2927
|
save() {
|
|
4225
2928
|
let promise = Promise.all(this.map(record => this.store.saveRecord(record))).then(() => this);
|
|
4226
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
|
|
4227
|
-
return promiseArray(promise);
|
|
4228
|
-
}
|
|
4229
2929
|
return promise;
|
|
4230
2930
|
}
|
|
4231
2931
|
}, (_descriptor2 = _applyDecoratedDescriptor(_class3.prototype, "isUpdating", [tracked], {
|
|
@@ -4236,27 +2936,6 @@ let IdentifierArray = (_class3 = class IdentifierArray {
|
|
|
4236
2936
|
return false;
|
|
4237
2937
|
}
|
|
4238
2938
|
}), _applyDecoratedDescriptor(_class3.prototype, "length", [dependentKeyCompat], Object.getOwnPropertyDescriptor(_class3.prototype, "length"), _class3.prototype)), _class3);
|
|
4239
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_SNAPSHOT_MODEL_CLASS_ACCESS)) {
|
|
4240
|
-
Object.defineProperty(IdentifierArray.prototype, 'type', {
|
|
4241
|
-
get() {
|
|
4242
|
-
deprecate(`Using RecordArray.type to access the ModelClass for a record is deprecated. Use store.modelFor(<modelName>) instead.`, false, {
|
|
4243
|
-
id: 'ember-data:deprecate-snapshot-model-class-access',
|
|
4244
|
-
until: '5.0',
|
|
4245
|
-
for: 'ember-data',
|
|
4246
|
-
since: {
|
|
4247
|
-
available: '4.5.0',
|
|
4248
|
-
enabled: '4.5.0'
|
|
4249
|
-
}
|
|
4250
|
-
});
|
|
4251
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
4252
|
-
if (!this.modelName) {
|
|
4253
|
-
return null;
|
|
4254
|
-
}
|
|
4255
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
4256
|
-
return this.store.modelFor(this.modelName);
|
|
4257
|
-
}
|
|
4258
|
-
});
|
|
4259
|
-
}
|
|
4260
2939
|
class Collection extends IdentifierArray {
|
|
4261
2940
|
constructor(options) {
|
|
4262
2941
|
super(options);
|
|
@@ -4276,9 +2955,6 @@ class Collection extends IdentifierArray {
|
|
|
4276
2955
|
const promise = store.query(this.modelName, query, {
|
|
4277
2956
|
_recordArray: this
|
|
4278
2957
|
});
|
|
4279
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
|
|
4280
|
-
return promiseArray(promise);
|
|
4281
|
-
}
|
|
4282
2958
|
return promise;
|
|
4283
2959
|
}
|
|
4284
2960
|
destroy() {
|
|
@@ -4292,286 +2968,6 @@ Collection.prototype.query = null;
|
|
|
4292
2968
|
|
|
4293
2969
|
// Ensure instanceof works correctly
|
|
4294
2970
|
//Object.setPrototypeOf(IdentifierArray.prototype, Array.prototype);
|
|
4295
|
-
|
|
4296
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_ARRAY_LIKE)) {
|
|
4297
|
-
IdentifierArray.prototype.DEPRECATED_CLASS_NAME = 'RecordArray';
|
|
4298
|
-
Collection.prototype.DEPRECATED_CLASS_NAME = 'RecordArray';
|
|
4299
|
-
const EmberObjectMethods = ['addObserver', 'cacheFor', 'decrementProperty', 'get', 'getProperties', 'incrementProperty', 'notifyPropertyChange', 'removeObserver', 'set', 'setProperties', 'toggleProperty'];
|
|
4300
|
-
EmberObjectMethods.forEach(method => {
|
|
4301
|
-
IdentifierArray.prototype[method] = function delegatedMethod(...args) {
|
|
4302
|
-
deprecate(`The EmberObject ${method} method on the class ${this.DEPRECATED_CLASS_NAME} is deprecated. Use dot-notation javascript get/set access instead.`, false, {
|
|
4303
|
-
id: 'ember-data:deprecate-array-like',
|
|
4304
|
-
until: '5.0',
|
|
4305
|
-
since: {
|
|
4306
|
-
enabled: '4.7',
|
|
4307
|
-
available: '4.7'
|
|
4308
|
-
},
|
|
4309
|
-
for: 'ember-data'
|
|
4310
|
-
});
|
|
4311
|
-
return Ember[method](this, ...args);
|
|
4312
|
-
};
|
|
4313
|
-
});
|
|
4314
|
-
IdentifierArray.prototype.addObject = function (obj) {
|
|
4315
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'addObject', 'push');
|
|
4316
|
-
let index = this.indexOf(obj);
|
|
4317
|
-
if (index === -1) {
|
|
4318
|
-
this.push(obj);
|
|
4319
|
-
}
|
|
4320
|
-
return this;
|
|
4321
|
-
};
|
|
4322
|
-
IdentifierArray.prototype.addObjects = function (objs) {
|
|
4323
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'addObjects', 'push');
|
|
4324
|
-
objs.forEach(obj => {
|
|
4325
|
-
let index = this.indexOf(obj);
|
|
4326
|
-
if (index === -1) {
|
|
4327
|
-
this.push(obj);
|
|
4328
|
-
}
|
|
4329
|
-
});
|
|
4330
|
-
return this;
|
|
4331
|
-
};
|
|
4332
|
-
IdentifierArray.prototype.popObject = function () {
|
|
4333
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'popObject', 'pop');
|
|
4334
|
-
return this.pop();
|
|
4335
|
-
};
|
|
4336
|
-
IdentifierArray.prototype.pushObject = function (obj) {
|
|
4337
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'pushObject', 'push');
|
|
4338
|
-
this.push(obj);
|
|
4339
|
-
return obj;
|
|
4340
|
-
};
|
|
4341
|
-
IdentifierArray.prototype.pushObjects = function (objs) {
|
|
4342
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'pushObjects', 'push');
|
|
4343
|
-
this.push(...objs);
|
|
4344
|
-
return this;
|
|
4345
|
-
};
|
|
4346
|
-
IdentifierArray.prototype.shiftObject = function () {
|
|
4347
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'shiftObject', 'shift');
|
|
4348
|
-
return this.shift();
|
|
4349
|
-
};
|
|
4350
|
-
IdentifierArray.prototype.unshiftObject = function (obj) {
|
|
4351
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'unshiftObject', 'unshift');
|
|
4352
|
-
this.unshift(obj);
|
|
4353
|
-
return obj;
|
|
4354
|
-
};
|
|
4355
|
-
IdentifierArray.prototype.unshiftObjects = function (objs) {
|
|
4356
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'unshiftObjects', 'unshift');
|
|
4357
|
-
this.unshift(...objs);
|
|
4358
|
-
return this;
|
|
4359
|
-
};
|
|
4360
|
-
IdentifierArray.prototype.objectAt = function (index) {
|
|
4361
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'objectAt', 'at');
|
|
4362
|
-
//For negative index values go back from the end of the array
|
|
4363
|
-
let arrIndex = Math.sign(index) === -1 ? this.length + index : index;
|
|
4364
|
-
return this[arrIndex];
|
|
4365
|
-
};
|
|
4366
|
-
IdentifierArray.prototype.objectsAt = function (indeces) {
|
|
4367
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'objectsAt', 'at');
|
|
4368
|
-
return indeces.map(index => this.objectAt(index));
|
|
4369
|
-
};
|
|
4370
|
-
IdentifierArray.prototype.removeAt = function (index) {
|
|
4371
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'removeAt', 'splice');
|
|
4372
|
-
this.splice(index, 1);
|
|
4373
|
-
return this;
|
|
4374
|
-
};
|
|
4375
|
-
IdentifierArray.prototype.insertAt = function (index, obj) {
|
|
4376
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'insertAt', 'splice');
|
|
4377
|
-
this.splice(index, 0, obj);
|
|
4378
|
-
return this;
|
|
4379
|
-
};
|
|
4380
|
-
IdentifierArray.prototype.removeObject = function (obj) {
|
|
4381
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'removeObject', 'splice');
|
|
4382
|
-
const index = this.indexOf(obj);
|
|
4383
|
-
if (index !== -1) {
|
|
4384
|
-
this.splice(index, 1);
|
|
4385
|
-
}
|
|
4386
|
-
return this;
|
|
4387
|
-
};
|
|
4388
|
-
IdentifierArray.prototype.removeObjects = function (objs) {
|
|
4389
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'removeObjects', 'splice');
|
|
4390
|
-
objs.forEach(obj => {
|
|
4391
|
-
const index = this.indexOf(obj);
|
|
4392
|
-
if (index !== -1) {
|
|
4393
|
-
this.splice(index, 1);
|
|
4394
|
-
}
|
|
4395
|
-
});
|
|
4396
|
-
return this;
|
|
4397
|
-
};
|
|
4398
|
-
IdentifierArray.prototype.toArray = function () {
|
|
4399
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'toArray', 'slice');
|
|
4400
|
-
return this.slice();
|
|
4401
|
-
};
|
|
4402
|
-
IdentifierArray.prototype.replace = function (idx, amt, objects) {
|
|
4403
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'replace', 'splice');
|
|
4404
|
-
if (objects) {
|
|
4405
|
-
this.splice(idx, amt, ...objects);
|
|
4406
|
-
} else {
|
|
4407
|
-
this.splice(idx, amt);
|
|
4408
|
-
}
|
|
4409
|
-
};
|
|
4410
|
-
IdentifierArray.prototype.clear = function () {
|
|
4411
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'clear', 'length = 0');
|
|
4412
|
-
this.splice(0, this.length);
|
|
4413
|
-
return this;
|
|
4414
|
-
};
|
|
4415
|
-
IdentifierArray.prototype.setObjects = function (objects) {
|
|
4416
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'setObjects', '`arr.length = 0; arr.push(objects);`');
|
|
4417
|
-
assert(`${this.DEPRECATED_CLASS_NAME}.setObjects expects to receive an array as its argument`, Array.isArray(objects));
|
|
4418
|
-
this.splice(0, this.length);
|
|
4419
|
-
this.push(...objects);
|
|
4420
|
-
return this;
|
|
4421
|
-
};
|
|
4422
|
-
IdentifierArray.prototype.reverseObjects = function () {
|
|
4423
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'reverseObjects', 'reverse');
|
|
4424
|
-
this.reverse();
|
|
4425
|
-
return this;
|
|
4426
|
-
};
|
|
4427
|
-
IdentifierArray.prototype.compact = function () {
|
|
4428
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'compact', 'filter');
|
|
4429
|
-
return this.filter(v => v !== null && v !== undefined);
|
|
4430
|
-
};
|
|
4431
|
-
IdentifierArray.prototype.any = function (callback, target) {
|
|
4432
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'any', 'some');
|
|
4433
|
-
return this.some(callback, target);
|
|
4434
|
-
};
|
|
4435
|
-
IdentifierArray.prototype.isAny = function (prop, value) {
|
|
4436
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'isAny', 'some');
|
|
4437
|
-
let hasValue = arguments.length === 2;
|
|
4438
|
-
return this.some(v => hasValue ? v[prop] === value : v[prop] === true);
|
|
4439
|
-
};
|
|
4440
|
-
IdentifierArray.prototype.isEvery = function (prop, value) {
|
|
4441
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'isEvery', 'every');
|
|
4442
|
-
let hasValue = arguments.length === 2;
|
|
4443
|
-
return this.every(v => hasValue ? v[prop] === value : v[prop] === true);
|
|
4444
|
-
};
|
|
4445
|
-
IdentifierArray.prototype.getEach = function (key) {
|
|
4446
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'getEach', 'map');
|
|
4447
|
-
return this.map(value => get(value, key));
|
|
4448
|
-
};
|
|
4449
|
-
IdentifierArray.prototype.mapBy = function (key) {
|
|
4450
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'mapBy', 'map');
|
|
4451
|
-
return this.map(value => get(value, key));
|
|
4452
|
-
};
|
|
4453
|
-
IdentifierArray.prototype.findBy = function (key, value) {
|
|
4454
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'findBy', 'find');
|
|
4455
|
-
if (arguments.length === 2) {
|
|
4456
|
-
return this.find(val => {
|
|
4457
|
-
return get(val, key) === value;
|
|
4458
|
-
});
|
|
4459
|
-
} else {
|
|
4460
|
-
return this.find(val => Boolean(get(val, key)));
|
|
4461
|
-
}
|
|
4462
|
-
};
|
|
4463
|
-
IdentifierArray.prototype.filterBy = function (key, value) {
|
|
4464
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'filterBy', 'filter');
|
|
4465
|
-
if (arguments.length === 2) {
|
|
4466
|
-
return this.filter(record => {
|
|
4467
|
-
return get(record, key) === value;
|
|
4468
|
-
});
|
|
4469
|
-
}
|
|
4470
|
-
return this.filter(record => {
|
|
4471
|
-
return Boolean(get(record, key));
|
|
4472
|
-
});
|
|
4473
|
-
};
|
|
4474
|
-
IdentifierArray.prototype.sortBy = function (...sortKeys) {
|
|
4475
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'sortBy', '.slice().sort');
|
|
4476
|
-
return this.slice().sort((a, b) => {
|
|
4477
|
-
for (let i = 0; i < sortKeys.length; i++) {
|
|
4478
|
-
let key = sortKeys[i];
|
|
4479
|
-
let propA = get(a, key);
|
|
4480
|
-
let propB = get(b, key);
|
|
4481
|
-
// return 1 or -1 else continue to the next sortKey
|
|
4482
|
-
let compareValue = compare(propA, propB);
|
|
4483
|
-
if (compareValue) {
|
|
4484
|
-
return compareValue;
|
|
4485
|
-
}
|
|
4486
|
-
}
|
|
4487
|
-
return 0;
|
|
4488
|
-
});
|
|
4489
|
-
};
|
|
4490
|
-
|
|
4491
|
-
// @ts-expect-error
|
|
4492
|
-
IdentifierArray.prototype.invoke = function (key, ...args) {
|
|
4493
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'invoke', 'forEach');
|
|
4494
|
-
return this.map(value => value[key](...args));
|
|
4495
|
-
};
|
|
4496
|
-
|
|
4497
|
-
// @ts-expect-error
|
|
4498
|
-
IdentifierArray.prototype.addArrayObserver = function () {
|
|
4499
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'addArrayObserver', 'derived state or reacting at the change source');
|
|
4500
|
-
};
|
|
4501
|
-
|
|
4502
|
-
// @ts-expect-error
|
|
4503
|
-
IdentifierArray.prototype.removeArrayObserver = function () {
|
|
4504
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'removeArrayObserver', 'derived state or reacting at the change source');
|
|
4505
|
-
};
|
|
4506
|
-
|
|
4507
|
-
// @ts-expect-error
|
|
4508
|
-
IdentifierArray.prototype.arrayContentWillChange = function () {
|
|
4509
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'arrayContentWillChange', 'derived state or reacting at the change source');
|
|
4510
|
-
};
|
|
4511
|
-
|
|
4512
|
-
// @ts-expect-error
|
|
4513
|
-
IdentifierArray.prototype.arrayContentDidChange = function () {
|
|
4514
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'arrayContentDidChange', 'derived state or reacting at the change source.');
|
|
4515
|
-
};
|
|
4516
|
-
IdentifierArray.prototype.reject = function (callback, target) {
|
|
4517
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'reject', 'filter');
|
|
4518
|
-
assert('`reject` expects a function as first argument.', typeof callback === 'function');
|
|
4519
|
-
return this.filter((...args) => {
|
|
4520
|
-
return !callback.apply(target, args);
|
|
4521
|
-
});
|
|
4522
|
-
};
|
|
4523
|
-
IdentifierArray.prototype.rejectBy = function (key, value) {
|
|
4524
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'rejectBy', 'filter');
|
|
4525
|
-
if (arguments.length === 2) {
|
|
4526
|
-
return this.filter(record => {
|
|
4527
|
-
return get(record, key) !== value;
|
|
4528
|
-
});
|
|
4529
|
-
}
|
|
4530
|
-
return this.filter(record => {
|
|
4531
|
-
return !get(record, key);
|
|
4532
|
-
});
|
|
4533
|
-
};
|
|
4534
|
-
IdentifierArray.prototype.setEach = function (key, value) {
|
|
4535
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'setEach', 'forEach');
|
|
4536
|
-
this.forEach(item => set(item, key, value));
|
|
4537
|
-
};
|
|
4538
|
-
IdentifierArray.prototype.uniq = function () {
|
|
4539
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'uniq', 'filter');
|
|
4540
|
-
// all current managed arrays are already enforced as unique
|
|
4541
|
-
return this.slice();
|
|
4542
|
-
};
|
|
4543
|
-
|
|
4544
|
-
// @ts-expect-error
|
|
4545
|
-
IdentifierArray.prototype.uniqBy = function (key) {
|
|
4546
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'uniqBy', 'filter');
|
|
4547
|
-
// all current managed arrays are already enforced as unique
|
|
4548
|
-
let seen = new Set();
|
|
4549
|
-
let result = [];
|
|
4550
|
-
this.forEach(item => {
|
|
4551
|
-
let value = get(item, key);
|
|
4552
|
-
if (seen.has(value)) {
|
|
4553
|
-
return;
|
|
4554
|
-
}
|
|
4555
|
-
seen.add(value);
|
|
4556
|
-
result.push(item);
|
|
4557
|
-
});
|
|
4558
|
-
return result;
|
|
4559
|
-
};
|
|
4560
|
-
IdentifierArray.prototype.without = function (value) {
|
|
4561
|
-
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'without', 'slice');
|
|
4562
|
-
const newArr = this.slice();
|
|
4563
|
-
const index = this.indexOf(value);
|
|
4564
|
-
if (index !== -1) {
|
|
4565
|
-
newArr.splice(index, 1);
|
|
4566
|
-
}
|
|
4567
|
-
return newArr;
|
|
4568
|
-
};
|
|
4569
|
-
|
|
4570
|
-
// @ts-expect-error
|
|
4571
|
-
IdentifierArray.prototype.firstObject = null;
|
|
4572
|
-
// @ts-expect-error
|
|
4573
|
-
IdentifierArray.prototype.lastObject = null;
|
|
4574
|
-
}
|
|
4575
2971
|
function assertRecordPassedToHasMany(record) {
|
|
4576
2972
|
assert(`All elements of a hasMany relationship must be instances of Model, you passed $${typeof record}`, function () {
|
|
4577
2973
|
try {
|
|
@@ -4582,21 +2978,12 @@ function assertRecordPassedToHasMany(record) {
|
|
|
4582
2978
|
}
|
|
4583
2979
|
}());
|
|
4584
2980
|
}
|
|
4585
|
-
function extractIdentifierFromRecord$1(
|
|
4586
|
-
if (!
|
|
2981
|
+
function extractIdentifierFromRecord$1(record) {
|
|
2982
|
+
if (!record) {
|
|
4587
2983
|
return null;
|
|
4588
2984
|
}
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
assert('You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo relationship.', content !== undefined && content !== null);
|
|
4592
|
-
assertRecordPassedToHasMany(content);
|
|
4593
|
-
return recordIdentifierFor(content);
|
|
4594
|
-
}
|
|
4595
|
-
assertRecordPassedToHasMany(recordOrPromiseRecord);
|
|
4596
|
-
return recordIdentifierFor(recordOrPromiseRecord);
|
|
4597
|
-
}
|
|
4598
|
-
function isPromiseRecord$1(record) {
|
|
4599
|
-
return !!record.then;
|
|
2985
|
+
assertRecordPassedToHasMany(record);
|
|
2986
|
+
return recordIdentifierFor(record);
|
|
4600
2987
|
}
|
|
4601
2988
|
|
|
4602
2989
|
/**
|
|
@@ -5123,6 +3510,42 @@ class RequestStateService {
|
|
|
5123
3510
|
return null;
|
|
5124
3511
|
}
|
|
5125
3512
|
}
|
|
3513
|
+
function constructResource(type, id, lid) {
|
|
3514
|
+
if (typeof type === 'object' && type !== null) {
|
|
3515
|
+
let resource = type;
|
|
3516
|
+
if (isStableIdentifier(resource)) {
|
|
3517
|
+
return resource;
|
|
3518
|
+
}
|
|
3519
|
+
if ('id' in resource) {
|
|
3520
|
+
resource.id = coerceId(resource.id);
|
|
3521
|
+
}
|
|
3522
|
+
assert('Expected either id or lid to be a valid string', 'id' in resource && isNonEmptyString(resource.id) || isNonEmptyString(resource.lid));
|
|
3523
|
+
assert('if id is present, the type must be a string', !('id' in resource) || typeof resource.type === 'string');
|
|
3524
|
+
return resource;
|
|
3525
|
+
} else {
|
|
3526
|
+
const trueId = coerceId(id);
|
|
3527
|
+
if (!isNonEmptyString(trueId)) {
|
|
3528
|
+
if (isNonEmptyString(lid)) {
|
|
3529
|
+
return {
|
|
3530
|
+
lid
|
|
3531
|
+
};
|
|
3532
|
+
}
|
|
3533
|
+
throw new Error('Expected either id or lid to be a valid string');
|
|
3534
|
+
}
|
|
3535
|
+
assert('type must be a string', typeof type === 'string');
|
|
3536
|
+
if (isNonEmptyString(lid)) {
|
|
3537
|
+
return {
|
|
3538
|
+
type,
|
|
3539
|
+
id: trueId,
|
|
3540
|
+
lid
|
|
3541
|
+
};
|
|
3542
|
+
}
|
|
3543
|
+
return {
|
|
3544
|
+
type,
|
|
3545
|
+
id: trueId
|
|
3546
|
+
};
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
5126
3549
|
|
|
5127
3550
|
/**
|
|
5128
3551
|
@module @ember-data/store
|
|
@@ -5414,7 +3837,7 @@ class Store {
|
|
|
5414
3837
|
instantiateRecord(identifier, createRecordArgs) {
|
|
5415
3838
|
if (macroCondition(getOwnConfig().packages.HAS_MODEL_PACKAGE)) {
|
|
5416
3839
|
let modelName = identifier.type;
|
|
5417
|
-
const cache =
|
|
3840
|
+
const cache = this.cache;
|
|
5418
3841
|
// TODO deprecate allowing unknown args setting
|
|
5419
3842
|
let createOptions = {
|
|
5420
3843
|
_createProps: createRecordArgs,
|
|
@@ -5614,7 +4037,7 @@ class Store {
|
|
|
5614
4037
|
assert(`You need to pass a model name to the store's modelFor method`, modelName);
|
|
5615
4038
|
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string');
|
|
5616
4039
|
if (macroCondition(getOwnConfig().packages.HAS_MODEL_PACKAGE)) {
|
|
5617
|
-
let normalizedModelName = normalizeModelName
|
|
4040
|
+
let normalizedModelName = normalizeModelName(modelName);
|
|
5618
4041
|
let maybeFactory = getModelFactory(this, this._modelFactoryCache, normalizedModelName);
|
|
5619
4042
|
|
|
5620
4043
|
// for factorFor factory/class split
|
|
@@ -5670,7 +4093,7 @@ class Store {
|
|
|
5670
4093
|
let record;
|
|
5671
4094
|
_backburner.join(() => {
|
|
5672
4095
|
this._join(() => {
|
|
5673
|
-
let normalizedModelName = normalizeModelName
|
|
4096
|
+
let normalizedModelName = normalizeModelName(modelName);
|
|
5674
4097
|
let properties = {
|
|
5675
4098
|
...inputProperties
|
|
5676
4099
|
};
|
|
@@ -5700,8 +4123,8 @@ class Store {
|
|
|
5700
4123
|
assert(`The id ${properties.id} has already been used with another '${normalizedModelName}' record.`, !identifier);
|
|
5701
4124
|
}
|
|
5702
4125
|
const identifier = this.identifierCache.createIdentifierForNewRecord(resource);
|
|
5703
|
-
const cache =
|
|
5704
|
-
const createOptions = normalizeProperties(this, identifier, properties
|
|
4126
|
+
const cache = this.cache;
|
|
4127
|
+
const createOptions = normalizeProperties(this, identifier, properties);
|
|
5705
4128
|
const resultProps = cache.clientDidCreate(identifier, createOptions);
|
|
5706
4129
|
record = this._instanceCache.getRecord(identifier, resultProps);
|
|
5707
4130
|
});
|
|
@@ -5727,11 +4150,8 @@ class Store {
|
|
|
5727
4150
|
assertDestroyingStore(this, 'deleteRecord');
|
|
5728
4151
|
}
|
|
5729
4152
|
const identifier = peekRecordIdentifier(record);
|
|
5730
|
-
const cache =
|
|
5731
|
-
|
|
5732
|
-
bucket: 'resourceCache'
|
|
5733
|
-
}) : this.cache);
|
|
5734
|
-
assert(`expected a cache instance to exist for the record`, cache);
|
|
4153
|
+
const cache = this.cache;
|
|
4154
|
+
assert(`expected the record to be connected to a cache`, identifier);
|
|
5735
4155
|
this._join(() => {
|
|
5736
4156
|
cache.setIsDeleted(identifier, true);
|
|
5737
4157
|
if (cache.isNew(identifier)) {
|
|
@@ -5765,43 +4185,6 @@ class Store {
|
|
|
5765
4185
|
}
|
|
5766
4186
|
}
|
|
5767
4187
|
|
|
5768
|
-
/**
|
|
5769
|
-
@method find
|
|
5770
|
-
@param {String} modelName
|
|
5771
|
-
@param {String|Integer} id
|
|
5772
|
-
@param {Object} options
|
|
5773
|
-
@return {Promise} promise
|
|
5774
|
-
@deprecated
|
|
5775
|
-
@private
|
|
5776
|
-
*/
|
|
5777
|
-
find(modelName, id, options) {
|
|
5778
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
5779
|
-
assertDestroyingStore(this, 'find');
|
|
5780
|
-
}
|
|
5781
|
-
// The default `model` hook in Route calls `find(modelName, id)`,
|
|
5782
|
-
// that's why we have to keep this method around even though `findRecord` is
|
|
5783
|
-
// the public way to get a record by modelName and id.
|
|
5784
|
-
assert(`Using store.find(type) has been removed. Use store.findAll(modelName) to retrieve all records for a given type.`, arguments.length !== 1);
|
|
5785
|
-
assert(`Calling store.find(modelName, id, { preload: preload }) is no longer supported. Use store.findRecord(modelName, id, { preload: preload }) instead.`, !options);
|
|
5786
|
-
assert(`You need to pass the model name and id to the store's find method`, arguments.length === 2);
|
|
5787
|
-
assert(`You cannot pass '${id}' as id to the store's find method`, typeof id === 'string' || typeof id === 'number');
|
|
5788
|
-
assert(`Calling store.find() with a query object is no longer supported. Use store.query() instead.`, typeof id !== 'object');
|
|
5789
|
-
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string');
|
|
5790
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_STORE_FIND)) {
|
|
5791
|
-
deprecate(`Using store.find is deprecated, use store.findRecord instead. Likely this means you are relying on the implicit store fetching behavior of routes unknowingly.`, false, {
|
|
5792
|
-
id: 'ember-data:deprecate-store-find',
|
|
5793
|
-
since: {
|
|
5794
|
-
available: '4.5',
|
|
5795
|
-
enabled: '4.5'
|
|
5796
|
-
},
|
|
5797
|
-
for: 'ember-data',
|
|
5798
|
-
until: '5.0'
|
|
5799
|
-
});
|
|
5800
|
-
return this.findRecord(modelName, id);
|
|
5801
|
-
}
|
|
5802
|
-
assert(`store.find has been removed. Use store.findRecord instead.`);
|
|
5803
|
-
}
|
|
5804
|
-
|
|
5805
4188
|
/**
|
|
5806
4189
|
This method returns a record for a given identifier or type and id combination.
|
|
5807
4190
|
The `findRecord` method will always resolve its promise with the same
|
|
@@ -6093,7 +4476,7 @@ class Store {
|
|
|
6093
4476
|
options = id;
|
|
6094
4477
|
} else {
|
|
6095
4478
|
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${resource}`, typeof resource === 'string');
|
|
6096
|
-
const type = normalizeModelName
|
|
4479
|
+
const type = normalizeModelName(resource);
|
|
6097
4480
|
const normalizedId = ensureStringId(id);
|
|
6098
4481
|
resource = constructResource(type, normalizedId);
|
|
6099
4482
|
}
|
|
@@ -6120,11 +4503,6 @@ class Store {
|
|
|
6120
4503
|
[SkipCache]: true
|
|
6121
4504
|
}
|
|
6122
4505
|
});
|
|
6123
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
|
|
6124
|
-
return promiseObject(promise.then(document => {
|
|
6125
|
-
return document.content;
|
|
6126
|
-
}));
|
|
6127
|
-
}
|
|
6128
4506
|
return promise.then(document => {
|
|
6129
4507
|
return document.content;
|
|
6130
4508
|
});
|
|
@@ -6168,7 +4546,7 @@ class Store {
|
|
|
6168
4546
|
if (arguments.length === 1 && isMaybeIdentifier(resource)) {
|
|
6169
4547
|
resourceIdentifier = resource;
|
|
6170
4548
|
} else {
|
|
6171
|
-
const type = normalizeModelName
|
|
4549
|
+
const type = normalizeModelName(resource);
|
|
6172
4550
|
const normalizedId = ensureStringId(id);
|
|
6173
4551
|
resourceIdentifier = constructResource(type, normalizedId);
|
|
6174
4552
|
}
|
|
@@ -6225,7 +4603,7 @@ class Store {
|
|
|
6225
4603
|
}
|
|
6226
4604
|
assert(`You need to pass a model name to the store's peekRecord method`, identifier);
|
|
6227
4605
|
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${identifier}`, typeof identifier === 'string');
|
|
6228
|
-
const type = normalizeModelName
|
|
4606
|
+
const type = normalizeModelName(identifier);
|
|
6229
4607
|
const normalizedId = ensureStringId(id);
|
|
6230
4608
|
const resource = {
|
|
6231
4609
|
type,
|
|
@@ -6236,52 +4614,6 @@ class Store {
|
|
|
6236
4614
|
return isLoaded ? this._instanceCache.getRecord(stableIdentifier) : null;
|
|
6237
4615
|
}
|
|
6238
4616
|
|
|
6239
|
-
/**
|
|
6240
|
-
This method returns true if a record for a given modelName and id is already
|
|
6241
|
-
loaded in the store. Use this function to know beforehand if a findRecord()
|
|
6242
|
-
will result in a request or that it will be a cache hit.
|
|
6243
|
-
Example
|
|
6244
|
-
```javascript
|
|
6245
|
-
store.hasRecordForId('post', 1); // false
|
|
6246
|
-
store.findRecord('post', 1).then(function() {
|
|
6247
|
-
store.hasRecordForId('post', 1); // true
|
|
6248
|
-
});
|
|
6249
|
-
```
|
|
6250
|
-
@method hasRecordForId
|
|
6251
|
-
@deprecated
|
|
6252
|
-
@public
|
|
6253
|
-
@param {String} modelName
|
|
6254
|
-
@param {(String|Integer)} id
|
|
6255
|
-
@return {Boolean}
|
|
6256
|
-
*/
|
|
6257
|
-
hasRecordForId(modelName, id) {
|
|
6258
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_HAS_RECORD)) {
|
|
6259
|
-
deprecate(`store.hasRecordForId has been deprecated in favor of store.peekRecord`, false, {
|
|
6260
|
-
id: 'ember-data:deprecate-has-record-for-id',
|
|
6261
|
-
since: {
|
|
6262
|
-
available: '4.5',
|
|
6263
|
-
enabled: '4.5'
|
|
6264
|
-
},
|
|
6265
|
-
until: '5.0',
|
|
6266
|
-
for: 'ember-data'
|
|
6267
|
-
});
|
|
6268
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
6269
|
-
assertDestroyingStore(this, 'hasRecordForId');
|
|
6270
|
-
}
|
|
6271
|
-
assert(`You need to pass a model name to the store's hasRecordForId method`, modelName);
|
|
6272
|
-
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string');
|
|
6273
|
-
const type = normalizeModelName$1(modelName);
|
|
6274
|
-
const trueId = ensureStringId(id);
|
|
6275
|
-
const resource = {
|
|
6276
|
-
type,
|
|
6277
|
-
id: trueId
|
|
6278
|
-
};
|
|
6279
|
-
const identifier = this.identifierCache.peekRecordIdentifier(resource);
|
|
6280
|
-
return Boolean(identifier && this._instanceCache.recordIsLoaded(identifier));
|
|
6281
|
-
}
|
|
6282
|
-
assert(`store.hasRecordForId has been removed`);
|
|
6283
|
-
}
|
|
6284
|
-
|
|
6285
4617
|
/**
|
|
6286
4618
|
This method delegates a query to the adapter. This is the one place where
|
|
6287
4619
|
adapter-level semantics are exposed to the application.
|
|
@@ -6329,7 +4661,7 @@ class Store {
|
|
|
6329
4661
|
const promise = this.request({
|
|
6330
4662
|
op: 'query',
|
|
6331
4663
|
data: {
|
|
6332
|
-
type: normalizeModelName
|
|
4664
|
+
type: normalizeModelName(modelName),
|
|
6333
4665
|
query,
|
|
6334
4666
|
options: options || {}
|
|
6335
4667
|
},
|
|
@@ -6337,9 +4669,6 @@ class Store {
|
|
|
6337
4669
|
[SkipCache]: true
|
|
6338
4670
|
}
|
|
6339
4671
|
});
|
|
6340
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
|
|
6341
|
-
return promiseArray(promise.then(document => document.content));
|
|
6342
|
-
}
|
|
6343
4672
|
return promise.then(document => document.content);
|
|
6344
4673
|
}
|
|
6345
4674
|
|
|
@@ -6434,7 +4763,7 @@ class Store {
|
|
|
6434
4763
|
const promise = this.request({
|
|
6435
4764
|
op: 'queryRecord',
|
|
6436
4765
|
data: {
|
|
6437
|
-
type: normalizeModelName
|
|
4766
|
+
type: normalizeModelName(modelName),
|
|
6438
4767
|
query,
|
|
6439
4768
|
options: options || {}
|
|
6440
4769
|
},
|
|
@@ -6442,9 +4771,6 @@ class Store {
|
|
|
6442
4771
|
[SkipCache]: true
|
|
6443
4772
|
}
|
|
6444
4773
|
});
|
|
6445
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
|
|
6446
|
-
return promiseObject(promise.then(document => document.content));
|
|
6447
|
-
}
|
|
6448
4774
|
return promise.then(document => document.content);
|
|
6449
4775
|
}
|
|
6450
4776
|
|
|
@@ -6608,16 +4934,13 @@ class Store {
|
|
|
6608
4934
|
const promise = this.request({
|
|
6609
4935
|
op: 'findAll',
|
|
6610
4936
|
data: {
|
|
6611
|
-
type: normalizeModelName
|
|
4937
|
+
type: normalizeModelName(modelName),
|
|
6612
4938
|
options: options || {}
|
|
6613
4939
|
},
|
|
6614
4940
|
cacheOptions: {
|
|
6615
4941
|
[SkipCache]: true
|
|
6616
4942
|
}
|
|
6617
4943
|
});
|
|
6618
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
|
|
6619
|
-
return promiseArray(promise.then(document => document.content));
|
|
6620
|
-
}
|
|
6621
4944
|
return promise.then(document => document.content);
|
|
6622
4945
|
}
|
|
6623
4946
|
|
|
@@ -6647,7 +4970,7 @@ class Store {
|
|
|
6647
4970
|
}
|
|
6648
4971
|
assert(`You need to pass a model name to the store's peekAll method`, modelName);
|
|
6649
4972
|
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string');
|
|
6650
|
-
let type = normalizeModelName
|
|
4973
|
+
let type = normalizeModelName(modelName);
|
|
6651
4974
|
return this.recordArrayManager.liveArrayFor(type);
|
|
6652
4975
|
}
|
|
6653
4976
|
|
|
@@ -6684,7 +5007,7 @@ class Store {
|
|
|
6684
5007
|
this.recordArrayManager.clear();
|
|
6685
5008
|
this._instanceCache.clear();
|
|
6686
5009
|
} else {
|
|
6687
|
-
let normalizedModelName = normalizeModelName
|
|
5010
|
+
let normalizedModelName = normalizeModelName(modelName);
|
|
6688
5011
|
this._instanceCache.clear(normalizedModelName);
|
|
6689
5012
|
}
|
|
6690
5013
|
});
|
|
@@ -6863,15 +5186,9 @@ class Store {
|
|
|
6863
5186
|
}
|
|
6864
5187
|
let ret;
|
|
6865
5188
|
this._join(() => {
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
});
|
|
6870
|
-
} else {
|
|
6871
|
-
ret = this.cache.put({
|
|
6872
|
-
content: jsonApiDoc
|
|
6873
|
-
});
|
|
6874
|
-
}
|
|
5189
|
+
ret = this.cache.put({
|
|
5190
|
+
content: jsonApiDoc
|
|
5191
|
+
});
|
|
6875
5192
|
});
|
|
6876
5193
|
this._enableAsyncFlush = null;
|
|
6877
5194
|
return ret.data;
|
|
@@ -6934,7 +5251,7 @@ class Store {
|
|
|
6934
5251
|
} else {
|
|
6935
5252
|
payload = inputPayload;
|
|
6936
5253
|
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string');
|
|
6937
|
-
let normalizedModelName = normalizeModelName
|
|
5254
|
+
let normalizedModelName = normalizeModelName(modelName);
|
|
6938
5255
|
serializer = this.serializerFor(normalizedModelName);
|
|
6939
5256
|
}
|
|
6940
5257
|
assert(`You must define a pushPayload method in your serializer in order to call store.pushPayload`, serializer.pushPayload);
|
|
@@ -6969,17 +5286,14 @@ class Store {
|
|
|
6969
5286
|
}
|
|
6970
5287
|
assert(`Unable to initate save for a record in a disconnected state`, storeFor(record));
|
|
6971
5288
|
let identifier = recordIdentifierFor(record);
|
|
6972
|
-
const cache =
|
|
6973
|
-
|
|
6974
|
-
bucket: 'resourceCache'
|
|
6975
|
-
}) : this.cache);
|
|
6976
|
-
if (!cache) {
|
|
5289
|
+
const cache = this.cache;
|
|
5290
|
+
if (!identifier) {
|
|
6977
5291
|
// this commonly means we're disconnected
|
|
6978
5292
|
// but just in case we reject here to prevent bad things.
|
|
6979
5293
|
return Promise.reject(`Record Is Disconnected`);
|
|
6980
5294
|
}
|
|
6981
5295
|
// TODO we used to check if the record was destroyed here
|
|
6982
|
-
assert(`Cannot initiate a save request for an unloaded record: ${identifier}`,
|
|
5296
|
+
assert(`Cannot initiate a save request for an unloaded record: ${identifier}`, this._instanceCache.recordIsLoaded(identifier));
|
|
6983
5297
|
if (resourceIsFullyDeleted(this._instanceCache, identifier)) {
|
|
6984
5298
|
return Promise.resolve(record);
|
|
6985
5299
|
}
|
|
@@ -7044,26 +5358,12 @@ class Store {
|
|
|
7044
5358
|
if (!cache) {
|
|
7045
5359
|
cache = this._instanceCache.cache = this.createCache(this._instanceCache._storeWrapper);
|
|
7046
5360
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
7047
|
-
cache = new
|
|
5361
|
+
cache = new CacheManager(cache);
|
|
7048
5362
|
}
|
|
7049
5363
|
}
|
|
7050
5364
|
return cache;
|
|
7051
5365
|
}
|
|
7052
5366
|
|
|
7053
|
-
/**
|
|
7054
|
-
* [DEPRECATED] use Store.createCache
|
|
7055
|
-
*
|
|
7056
|
-
* Instantiation hook allowing applications or addons to configure the store
|
|
7057
|
-
* to utilize a custom RecordData implementation.
|
|
7058
|
-
*
|
|
7059
|
-
* @method createRecordDataFor (hook)
|
|
7060
|
-
* @deprecated
|
|
7061
|
-
* @public
|
|
7062
|
-
* @param identifier
|
|
7063
|
-
* @param storeWrapper
|
|
7064
|
-
* @returns {Cache}
|
|
7065
|
-
*/
|
|
7066
|
-
|
|
7067
5367
|
/**
|
|
7068
5368
|
`normalize` converts a json payload into the normalized form that
|
|
7069
5369
|
[push](../methods/push?anchor=push) expects.
|
|
@@ -7088,7 +5388,7 @@ class Store {
|
|
|
7088
5388
|
}
|
|
7089
5389
|
assert(`You need to pass a model name to the store's normalize method`, modelName);
|
|
7090
5390
|
assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${typeof modelName}`, typeof modelName === 'string');
|
|
7091
|
-
let normalizedModelName = normalizeModelName
|
|
5391
|
+
let normalizedModelName = normalizeModelName(modelName);
|
|
7092
5392
|
let serializer = this.serializerFor(normalizedModelName);
|
|
7093
5393
|
let model = this.modelFor(normalizedModelName);
|
|
7094
5394
|
assert(`You must define a normalize method in your serializer in order to call store.normalize`, serializer?.normalize);
|
|
@@ -7113,7 +5413,7 @@ class Store {
|
|
|
7113
5413
|
}
|
|
7114
5414
|
assert(`You need to pass a model name to the store's adapterFor method`, modelName);
|
|
7115
5415
|
assert(`Passing classes to store.adapterFor has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string');
|
|
7116
|
-
let normalizedModelName = normalizeModelName
|
|
5416
|
+
let normalizedModelName = normalizeModelName(modelName);
|
|
7117
5417
|
let {
|
|
7118
5418
|
_adapterCache
|
|
7119
5419
|
} = this;
|
|
@@ -7137,25 +5437,6 @@ class Store {
|
|
|
7137
5437
|
_adapterCache.application = adapter;
|
|
7138
5438
|
return adapter;
|
|
7139
5439
|
}
|
|
7140
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_JSON_API_FALLBACK)) {
|
|
7141
|
-
// final fallback, no model specific adapter, no application adapter, no
|
|
7142
|
-
// `adapter` property on store: use json-api adapter
|
|
7143
|
-
adapter = _adapterCache['-json-api'] || owner.lookup('adapter:-json-api');
|
|
7144
|
-
if (adapter !== undefined) {
|
|
7145
|
-
deprecate(`Your application is utilizing a deprecated hidden fallback adapter (-json-api). Please implement an application adapter to function as your fallback.`, false, {
|
|
7146
|
-
id: 'ember-data:deprecate-secret-adapter-fallback',
|
|
7147
|
-
for: 'ember-data',
|
|
7148
|
-
until: '5.0',
|
|
7149
|
-
since: {
|
|
7150
|
-
available: '4.5',
|
|
7151
|
-
enabled: '4.5'
|
|
7152
|
-
}
|
|
7153
|
-
});
|
|
7154
|
-
_adapterCache[normalizedModelName] = adapter;
|
|
7155
|
-
_adapterCache['-json-api'] = adapter;
|
|
7156
|
-
return adapter;
|
|
7157
|
-
}
|
|
7158
|
-
}
|
|
7159
5440
|
assert(`No adapter was found for '${modelName}' and no 'application' adapter was found as a fallback.`);
|
|
7160
5441
|
}
|
|
7161
5442
|
|
|
@@ -7179,7 +5460,7 @@ class Store {
|
|
|
7179
5460
|
}
|
|
7180
5461
|
assert(`You need to pass a model name to the store's serializerFor method`, modelName);
|
|
7181
5462
|
assert(`Passing classes to store.serializerFor has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string');
|
|
7182
|
-
let normalizedModelName = normalizeModelName
|
|
5463
|
+
let normalizedModelName = normalizeModelName(modelName);
|
|
7183
5464
|
let {
|
|
7184
5465
|
_serializerCache
|
|
7185
5466
|
} = this;
|
|
@@ -7259,7 +5540,7 @@ function isDSModel(record) {
|
|
|
7259
5540
|
}
|
|
7260
5541
|
return !!record && 'constructor' in record && 'isModel' in record.constructor && record.constructor.isModel === true;
|
|
7261
5542
|
}
|
|
7262
|
-
function normalizeProperties(store, identifier, properties
|
|
5543
|
+
function normalizeProperties(store, identifier, properties) {
|
|
7263
5544
|
// assert here
|
|
7264
5545
|
if (properties !== undefined) {
|
|
7265
5546
|
if ('id' in properties) {
|
|
@@ -7285,9 +5566,9 @@ function normalizeProperties(store, identifier, properties, isForV1 = false) {
|
|
|
7285
5566
|
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
7286
5567
|
assertRecordsPassedToHasMany(properties[prop]);
|
|
7287
5568
|
}
|
|
7288
|
-
relationshipValue = extractIdentifiersFromRecords(properties[prop]
|
|
5569
|
+
relationshipValue = extractIdentifiersFromRecords(properties[prop]);
|
|
7289
5570
|
} else {
|
|
7290
|
-
relationshipValue = extractIdentifierFromRecord(properties[prop]
|
|
5571
|
+
relationshipValue = extractIdentifierFromRecord(properties[prop]);
|
|
7291
5572
|
}
|
|
7292
5573
|
properties[prop] = relationshipValue;
|
|
7293
5574
|
}
|
|
@@ -7309,53 +5590,19 @@ function assertRecordsPassedToHasMany(records) {
|
|
|
7309
5590
|
});
|
|
7310
5591
|
}());
|
|
7311
5592
|
}
|
|
7312
|
-
function extractIdentifiersFromRecords(records
|
|
7313
|
-
return records.map(record => extractIdentifierFromRecord(record
|
|
5593
|
+
function extractIdentifiersFromRecords(records) {
|
|
5594
|
+
return records.map(record => extractIdentifierFromRecord(record));
|
|
7314
5595
|
}
|
|
7315
|
-
function extractIdentifierFromRecord(recordOrPromiseRecord
|
|
5596
|
+
function extractIdentifierFromRecord(recordOrPromiseRecord) {
|
|
7316
5597
|
if (!recordOrPromiseRecord) {
|
|
7317
5598
|
return null;
|
|
7318
5599
|
}
|
|
7319
|
-
const extract =
|
|
7320
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
|
|
7321
|
-
if (isPromiseRecord(recordOrPromiseRecord)) {
|
|
7322
|
-
let content = recordOrPromiseRecord.content;
|
|
7323
|
-
assert('You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.', content !== undefined);
|
|
7324
|
-
deprecate(`You passed in a PromiseProxy to a Relationship API that now expects a resolved value. await the value before setting it.`, false, {
|
|
7325
|
-
id: 'ember-data:deprecate-promise-proxies',
|
|
7326
|
-
until: '5.0',
|
|
7327
|
-
since: {
|
|
7328
|
-
enabled: '4.7',
|
|
7329
|
-
available: '4.7'
|
|
7330
|
-
},
|
|
7331
|
-
for: 'ember-data'
|
|
7332
|
-
});
|
|
7333
|
-
return content ? extract(content) : null;
|
|
7334
|
-
}
|
|
7335
|
-
}
|
|
5600
|
+
const extract = recordIdentifierFor;
|
|
7336
5601
|
return extract(recordOrPromiseRecord);
|
|
7337
5602
|
}
|
|
7338
|
-
function isPromiseRecord(record) {
|
|
7339
|
-
return !!record.then;
|
|
7340
|
-
}
|
|
7341
5603
|
function secretInit(record, cache, identifier, store) {
|
|
7342
5604
|
setRecordIdentifier(record, identifier);
|
|
7343
5605
|
StoreMap.set(record, store);
|
|
7344
5606
|
setCacheFor(record, cache);
|
|
7345
5607
|
}
|
|
7346
|
-
|
|
7347
|
-
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_HELPERS)) {
|
|
7348
|
-
deprecate(`the helper function normalizeModelName is deprecated. You should use model names that are already normalized, or use string helpers of your own. This function is primarily an alias for dasherize from @ember/string.`, false, {
|
|
7349
|
-
id: 'ember-data:deprecate-normalize-modelname-helper',
|
|
7350
|
-
for: 'ember-data',
|
|
7351
|
-
until: '5.0',
|
|
7352
|
-
since: {
|
|
7353
|
-
available: '4.7',
|
|
7354
|
-
enabled: '4.7'
|
|
7355
|
-
}
|
|
7356
|
-
});
|
|
7357
|
-
return normalizeModelName$1(modelName);
|
|
7358
|
-
}
|
|
7359
|
-
assert(`normalizeModelName support has been removed`);
|
|
7360
|
-
}
|
|
7361
|
-
export { CacheHandler as C, IdentifierArray as I, MUTATE as M, RecordArrayManager as R, Store as S, _clearCaches as _, setIdentifierGenerationMethod as a, setIdentifierUpdateMethod as b, setIdentifierForgetMethod as c, setIdentifierResetMethod as d, coerceId as e, Collection as f, notifyArray as g, SOURCE as h, isStableIdentifier as i, IDENTIFIER_ARRAY_TAG as j, fastPush as k, removeRecordDataFor as l, normalizeModelName as n, peekCache as p, recordIdentifierFor as r, storeFor as s };
|
|
5608
|
+
export { CacheHandler as C, IdentifierArray as I, MUTATE as M, RecordArrayManager as R, Store as S, _clearCaches as _, setIdentifierGenerationMethod as a, setIdentifierUpdateMethod as b, setIdentifierForgetMethod as c, setIdentifierResetMethod as d, coerceId as e, Collection as f, SOURCE as g, IDENTIFIER_ARRAY_TAG as h, isStableIdentifier as i, fastPush as j, removeRecordDataFor as k, notifyArray as n, peekCache as p, recordIdentifierFor as r, storeFor as s };
|