@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$3, _descriptor$3, _descriptor2$1, _descriptor3, _descriptor4, _store$1, _request;
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$3 = (_store$1 = /*#__PURE__*/_classPrivateFieldKey("store"), _request = /*#__PURE__*/_classPrivateFieldKey("request"), class Document {
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$3, this);
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$1, {
68
+ Object.defineProperty(this, _store, {
95
69
  writable: true,
96
70
  value: void 0
97
71
  });
98
- _classPrivateFieldBase(this, _store$1)[_store$1] = 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$3 = _applyDecoratedDescriptor(_class$3.prototype, "links", [tracked], {
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$3.prototype, "data", [tracked], {
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$3.prototype, "errors", [tracked], {
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$3.prototype, "meta", [tracked], {
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$3);
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$1)[_store$1].request(Object.assign(options, {
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$1(type)}-${id}`;
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$1(resource.type);
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$1(data.type)) {
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$1(data.type);
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$1(data.type);
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$2, _descriptor$2;
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$2 = class RecordReference {
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$2, this);
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$2 = _applyDecoratedDescriptor(_class$2.prototype, "_ref", [tracked], {
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$2);
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
- * The CacheManager wraps a Cache enforcing that only
1518
- * the public API surface area is exposed.
1519
- *
1520
- * Hence, it is the value of `Store.cache`, wrapping
1521
- * the cache instance returned by `Store.createCache`.
1522
- *
1523
- * This class is the the return value of both the
1524
- * `recordDataFor` function supplied to the store
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
- // Cache Management
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
- * Perform an operation on the cache to update the remote state.
1637
- *
1638
- * Note: currently the only valid operation is a MergeOperation
1639
- * which occurs when a collision of identifiers is detected.
1640
- *
1641
- * @method patch
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
- cache.patch(op);
1652
- }
1653
-
1654
- /**
1655
- * Update resource data with a local mutation. Currently supports operations
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
- cache.mutate(mutation);
1486
+ this._flushNotifications();
1692
1487
  }
1693
1488
  }
1694
-
1695
- /**
1696
- * Peek resource data from the Cache.
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
- return cache.peek(identifier);
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
- * Peek the Cache for the existing request data associated with
1738
- * a cacheable request
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
- * Push resource data from a remote source into the cache for this identifier
1755
- *
1756
- * @method upsert
1757
- * @public
1758
- * @param identifier
1759
- * @param data
1760
- * @param hasRecord
1761
- * @returns {void | string[]} if `hasRecord` is true then calculated key changes should be returned
1762
- */
1763
- upsert(identifier, data, hasRecord) {
1764
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
1765
- // called by something V1
1766
- if (!isStableIdentifier(identifier)) {
1767
- data = identifier;
1768
- hasRecord = data;
1769
- identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
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
- // Cache Forking Support
1778
- // =====================
1540
+ /**
1541
+ @module @ember-data/store
1542
+ */
1779
1543
 
1780
- /**
1781
- * Create a fork of the cache from the current state.
1782
- *
1783
- * Applications should typically not call this method themselves,
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
- * Merge a fork back into a parent Cache.
1801
- *
1802
- * Applications should typically not call this method themselves,
1803
- * preferring instead to merge at the Store level, which will
1804
- * utilize this method to merge the caches.
1805
- *
1806
- * @method merge
1807
- * @param {Cache} cache
1808
- * @public
1809
- * @returns Promise<void>
1810
- */
1811
- merge(updates) {
1812
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
1813
- if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
1814
- throw new Error(`Expected cache to implement merge`);
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
- * Generate the list of changes applied to all
1821
- * record in the store.
1822
- *
1823
- * Each individual resource or document that has
1824
- * been mutated should be described as an individual
1825
- * `Change` entry in the returned array.
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
- // SSR Support
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
- * Serialize the entire contents of the Cache into a Stream
1865
- * which may be fed back into a new instance of the same Cache
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
- * hydrate a Cache from a Stream with content previously serialized
1882
- * from another instance of the same Cache, resolving when hydration
1883
- * is complete.
1884
- *
1885
- * This method should expect to be called both in the context of restoring
1886
- * the Cache during application rehydration after SSR **AND** at unknown
1887
- * times during the lifetime of an already booted application when it is
1888
- * desired to bulk-load additional information into the cache. This latter
1889
- * behavior supports optimizing pre/fetching of data for route transitions
1890
- * via data-only SSR modes.
1891
- *
1892
- * @method hydrate
1893
- * @param {ReadableStream} stream
1894
- * @returns {Promise<void>}
1895
- * @public
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
- // Cache
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
- * Retrieve the identifier for this v1 cache
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
- // Resource Support
1938
- // ================
1939
-
1940
- /**
1941
- * [LIFECYLCE] Signal to the cache that a new record has been instantiated on the client
1942
- *
1943
- * It returns properties from options that should be set on the record during the create
1944
- * process. This return value behavior is deprecated.
1945
- *
1946
- * @method clientDidCreate
1947
- * @public
1948
- * @param identifier
1949
- * @param options
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
- * Pass options to the cache that were supplied to a new record
1971
- * instantiated on the client.
1972
- *
1973
- * DEPRECATED: options are now passed via `clientDidCreate`
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
- * [LIFECYCLE] Signals to the cache that a resource
1989
- * will be part of a save transaction.
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
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
2015
- _classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.didCommit(data) : cache.didCommit(identifier, data);
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
- * [LIFECYCLE] Signals to the cache that a resource
2020
- * was update via a save transaction failed.
2021
- *
2022
- * @method commitWasRejected
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
- * [LIFECYCLE] Signals to the cache that all data for a resource
2033
- * should be cleared.
2034
- *
2035
- * @method unloadRecord
2036
- * @public
2037
- * @param identifier
2038
- */
2039
- unloadRecord(identifier) {
2040
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
2041
- if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
2042
- cache.unloadRecord();
2043
- } else {
2044
- cache.unloadRecord(identifier || _classPrivateFieldBase(this, _identifier)[_identifier]);
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
- // Granular Resource Data APIs
2049
- // ===========================
2050
-
2051
- /**
2052
- * Retrieve the data for an attribute from the cache
2053
- *
2054
- * @method getAttr
2055
- * @public
2056
- * @param identifier
2057
- * @param propertyName
2058
- * @returns {unknown}
2059
- */
2060
- getAttr(identifier, propertyName) {
2061
- // called by something V1
2062
- if (!isStableIdentifier(identifier)) {
2063
- propertyName = identifier;
2064
- identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
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
- * Mutate the data for an attribute in the cache
2072
- *
2073
- * @method setAttr
2074
- * @public
2075
- * @param identifier
2076
- * @param propertyName
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
- * Mutate the data for an attribute in the cache
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
- * Query the cache for the changed attributes of a resource.
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
- * Query the cache for the changed attributes of a resource.
2122
- *
2123
- * @method changedAttrs
2124
- * @public
2125
- * @deprecated
2126
- * @param identifier
2127
- * @returns
2128
- */
2129
- changedAttrs(identifier) {
2130
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
2131
- if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
2132
- return cache.changedAttributes();
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
- * Query the cache for whether any mutated attributes exist
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
- * Tell the cache to discard any uncommitted mutations to attributes
2167
- *
2168
- * DEPRECATED use rollbackAttrs
2169
- *
2170
- * @method rollbackAttributes
2171
- * @public
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
- // Relationships
2194
- // =============
1845
+ Preloaded data can be attributes and relationships passed in either as IDs or as actual
1846
+ models.
1847
+ */
2195
1848
 
2196
- // the third arg here is "private". In a world with only V2 it is not necessary
2197
- // but in one in which we must convert a call from V2 -> V1 it is required to do this
2198
- // or else to do nasty schema lookup things
2199
- // @runspired has implemented this concept in relationships spikes and is confident
2200
- // we do not need any signal about whether a relationship is a collection or not at this
2201
- // boundary
2202
- /**
2203
- * Query the cache for the current state of a relationship property
2204
- *
2205
- * @method getRelationship
2206
- * @public
2207
- * @param identifier
2208
- * @param propertyName
2209
- * @returns resource relationship object
2210
- */
2211
- getRelationship(identifier, propertyName, isCollection = false) {
2212
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
2213
- if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
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
- return cache.getRelationship(identifier, propertyName);
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
- * Query the cache for the current state of a belongsTo field
2222
- *
2223
- * DEPRECATED use `getRelationship`
2224
- *
2225
- * @method getBelongsTo
2226
- * @public
2227
- * @deprecated
2228
- * @param propertyName
2229
- * @returns single resource relationship object
2230
- */
2231
- getBelongsTo(propertyName) {
2232
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
2233
- if (_classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache)) {
2234
- return cache.getBelongsTo(propertyName);
2235
- } else {
2236
- let identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
2237
- return cache.getRelationship(identifier, propertyName);
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
- * Query the cache for the current state of a hasMany field
2243
- *
2244
- * DEPRECATED use `getRelationship`
2245
- *
2246
- * @method getHasMany
2247
- * @public
2248
- * @deprecated
2249
- * @param propertyName
2250
- * @returns single resource relationship object
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
- * Mutate the current state of a belongsTo relationship
2264
- *
2265
- * DEPRECATED use update
2266
- *
2267
- * @method setDirtyBelongsTo
2268
- * @public
2269
- * @deprecated
2270
- * @param propertyName
2271
- * @param value
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
- * Mutate the current state of a hasMany relationship by adding values
2285
- * An index may optionally be specified which the cache should use for
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
- * Mutate the current state of a hasMany relationship by removing values.
2310
- *
2311
- * DEPRECATED use update
2312
- *
2313
- * @method removeFromHasMany
2314
- * @deprecated
2315
- * @public
2316
- * @param propertyName
2317
- * @param value
2318
- */
2319
- removeFromHasMany(propertyName, value) {
2320
- const identifier = _classPrivateFieldBase(this, _identifier)[_identifier];
2321
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
2322
- _classPrivateFieldBase(this, _isDeprecated)[_isDeprecated](cache) ? cache.removeFromHasMany(propertyName, value) : cache.mutate({
2323
- op: 'removeFromRelatedRecords',
2324
- record: identifier,
2325
- field: propertyName,
2326
- value: value.map(v => v.getResourceIdentifier())
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
- * Mutate the current state of a hasMany relationship by replacing it entirely
2332
- *
2333
- * DEPRECATED use `setHasMany`
2334
- *
2335
- * @method setDirtyHasMany
2336
- * @public
2337
- * @deprecated
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
- // Resource State
2352
- // ===============
2353
-
2354
- /**
2355
- * Update the cache state for the given resource to be marked as locally deleted,
2356
- * or remove such a mark.
2357
- *
2358
- * @method setIsDeleted
2359
- * @public
2360
- * @param identifier
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
- * Query the cache for any validation errors applicable to the given resource.
2374
- *
2375
- * @method getErrors
2376
- * @public
2377
- * @param identifier
2378
- * @returns
2379
- */
2380
- getErrors(identifier) {
2381
- return _classPrivateFieldBase(this, _cache)[_cache].getErrors(identifier || _classPrivateFieldBase(this, _identifier)[_identifier]);
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
- * Query the cache for whether a given resource has any available data
2111
+ * Cache the response to a request
2386
2112
  *
2387
- * @method isEmpty
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
- isEmpty(identifier) {
2393
- const cache = _classPrivateFieldBase(this, _cache)[_cache];
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
- * Query the cache for whether a given resource was created locally and not
2399
- * yet persisted.
2138
+ * Perform an operation on the cache to update the remote state.
2400
2139
  *
2401
- * @method isNew
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 identifier
2404
- * @returns {boolean}
2145
+ * @param op the operation to perform
2146
+ * @returns {void}
2405
2147
  */
2406
- isNew(identifier) {
2407
- return _classPrivateFieldBase(this, _cache)[_cache].isNew(identifier || _classPrivateFieldBase(this, _identifier)[_identifier]);
2148
+ patch(op) {
2149
+ _classPrivateFieldBase(this, _cache)[_cache].patch(op);
2408
2150
  }
2409
2151
 
2410
2152
  /**
2411
- * Query the cache for whether a given resource is marked as deleted (but not
2412
- * necessarily persisted yet).
2153
+ * Update resource data with a local mutation. Currently supports operations
2154
+ * on relationships only.
2413
2155
  *
2414
- * @method isDeleted
2156
+ * @method mutate
2415
2157
  * @public
2416
- * @param identifier
2417
- * @returns {boolean}
2158
+ * @param mutation
2418
2159
  */
2419
- isDeleted(identifier) {
2420
- return _classPrivateFieldBase(this, _cache)[_cache].isDeleted(identifier || _classPrivateFieldBase(this, _identifier)[_identifier]);
2160
+ mutate(mutation) {
2161
+ _classPrivateFieldBase(this, _cache)[_cache].mutate(mutation);
2421
2162
  }
2422
2163
 
2423
2164
  /**
2424
- * Query the cache for whether a given resource has been deleted and that deletion
2425
- * has also been persisted.
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 isDeletionCommitted
2191
+ * @method peek
2428
2192
  * @public
2429
- * @param identifier
2430
- * @returns {boolean}
2193
+ * @param {StableRecordIdentifier | StableDocumentIdentifier} identifier
2194
+ * @returns {ResourceDocument | ResourceBlob | null} the known resource data
2431
2195
  */
2432
- isDeletionCommitted(identifier) {
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, _cache3)[_cache3].peek(identifier);
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, _cache3)[_cache3].peekRequest(identifier);
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
- // Cache
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, _cache3)[_cache3].upsert(identifier, data, hasRecord);
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
- // Attrs
2501
- // =====
2228
+ // Cache Forking Support
2229
+ // =====================
2502
2230
 
2503
- getAttr(identifier, propertyName) {
2504
- return _classPrivateFieldBase(this, _cache3)[_cache3].getAttr(identifier, propertyName);
2505
- }
2506
- setAttr(identifier, propertyName, value) {
2507
- _classPrivateFieldBase(this, _cache3)[_cache3].setAttr(identifier, propertyName, value);
2508
- }
2509
- changedAttrs(identifier) {
2510
- return _classPrivateFieldBase(this, _cache3)[_cache3].changedAttrs(identifier);
2511
- }
2512
- hasChangedAttrs(identifier) {
2513
- return _classPrivateFieldBase(this, _cache3)[_cache3].hasChangedAttrs(identifier);
2514
- }
2515
- rollbackAttrs(identifier) {
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
- // State
2526
- // =============
2527
-
2528
- setIsDeleted(identifier, isDeleted) {
2529
- _classPrivateFieldBase(this, _cache3)[_cache3].setIsDeleted(identifier, isDeleted);
2530
- }
2531
- getErrors(identifier) {
2532
- return _classPrivateFieldBase(this, _cache3)[_cache3].getErrors(identifier);
2533
- }
2534
- isEmpty(identifier) {
2535
- return _classPrivateFieldBase(this, _cache3)[_cache3].isEmpty(identifier);
2536
- }
2537
- isNew(identifier) {
2538
- return _classPrivateFieldBase(this, _cache3)[_cache3].isNew(identifier);
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
- function preloadData(store, identifier, preload) {
3388
- let jsonPayload = {};
3389
- //TODO(Igor) consider the polymorphic case
3390
- const schemas = store.getSchemaDefinitionService();
3391
- const relationships = schemas.relationshipsDefinitionFor(identifier);
3392
- Object.keys(preload).forEach(key => {
3393
- let preloadValue = preload[key];
3394
- let relationshipMeta = relationships[key];
3395
- if (relationshipMeta) {
3396
- if (!jsonPayload.relationships) {
3397
- jsonPayload.relationships = {};
3398
- }
3399
- jsonPayload.relationships[key] = preloadRelationship(relationshipMeta, preloadValue);
3400
- } else {
3401
- if (!jsonPayload.attributes) {
3402
- jsonPayload.attributes = {};
3403
- }
3404
- jsonPayload.attributes[key] = preloadValue;
3405
- }
3406
- });
3407
- const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? store._instanceCache.getResourceCache(identifier) : store.cache;
3408
- const hasRecord = Boolean(store._instanceCache.peek({
3409
- identifier,
3410
- bucket: 'record'
3411
- }));
3412
- cache.upsert(identifier, jsonPayload, hasRecord);
3413
- }
3414
- function preloadRelationship(schema, preloadValue) {
3415
- const relatedType = schema.type;
3416
- if (schema.kind === 'hasMany') {
3417
- assert('You need to pass in an array to set a hasMany property on a record', Array.isArray(preloadValue));
3418
- return {
3419
- data: preloadValue.map(value => _convertPreloadRelationshipToJSON(value, relatedType))
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
- findRecord('user', '1', { preload: { friends: ['1'] }});
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
- // Following the existing RD implementation
3484
- attributesDefinitionFor(identifier) {
3485
- let modelName, attributes;
3486
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_STRING_ARG_SCHEMAS)) {
3487
- if (typeof identifier === 'string') {
3488
- deprecate(`attributesDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`, false, {
3489
- id: 'ember-data:deprecate-string-arg-schemas',
3490
- for: 'ember-data',
3491
- until: '5.0',
3492
- since: {
3493
- enabled: '4.5',
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
- // Following the existing RD implementation
3516
- relationshipsDefinitionFor(identifier) {
3517
- let modelName, relationships;
3518
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_STRING_ARG_SCHEMAS)) {
3519
- if (typeof identifier === 'string') {
3520
- deprecate(`relationshipsDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`, false, {
3521
- id: 'ember-data:deprecate-string-arg-schemas',
3522
- for: 'ember-data',
3523
- until: '5.0',
3524
- since: {
3525
- enabled: '4.5',
3526
- available: '4.5'
3527
- }
3528
- });
3529
- modelName = identifier;
3530
- } else {
3531
- modelName = identifier.type;
3532
- }
3533
- } else {
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
- // if modelFor turns out to be a bottleneck we should replace with a Map
3580
- // and clear it during store teardown.
3581
- const AvailableShims = new WeakMap();
3582
- function getShimClass(store, modelName) {
3583
- let shims = AvailableShims.get(store);
3584
- if (!shims) {
3585
- shims = Object.create(null);
3586
- AvailableShims.set(store, shims);
3587
- }
3588
- let shim = shims[modelName];
3589
- if (shim === undefined) {
3590
- shim = shims[modelName] = new ShimModelClass(store, modelName);
3591
- }
3592
- return shim;
3593
- }
3594
- function mapFromHash(hash) {
3595
- let map = new Map();
3596
- for (let i in hash) {
3597
- if (Object.prototype.hasOwnProperty.call(hash, i)) {
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
- // Mimics the static apis of DSModel
3605
- class ShimModelClass {
3606
- constructor(store, modelName) {
3607
- this.__store = store;
3608
- this.modelName = modelName;
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
- get fields() {
3611
- let attrs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({
3612
- type: this.modelName
3613
- });
3614
- let relationships = this.__store.getSchemaDefinitionService().relationshipsDefinitionFor({
3615
- type: this.modelName
3616
- });
3617
- let fields = new Map();
3618
- Object.keys(attrs).forEach(key => fields.set(key, 'attribute'));
3619
- Object.keys(relationships).forEach(key => fields.set(key, relationships[key].kind));
3620
- return fields;
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
- get attributes() {
3623
- let attrs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({
3624
- type: this.modelName
3625
- });
3626
- return mapFromHash(attrs);
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
- get relationshipsByName() {
3629
- let relationships = this.__store.getSchemaDefinitionService().relationshipsDefinitionFor({
3630
- type: this.modelName
3631
- });
3632
- return mapFromHash(relationships);
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
- eachAttribute(callback, binding) {
3635
- let attrDefs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({
3636
- type: this.modelName
3637
- });
3638
- Object.keys(attrDefs).forEach(key => {
3639
- callback.call(binding, key, attrDefs[key]);
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
- eachRelationship(callback, binding) {
3643
- let relationshipDefs = this.__store.getSchemaDefinitionService().relationshipsDefinitionFor({
3644
- type: this.modelName
3645
- });
3646
- Object.keys(relationshipDefs).forEach(key => {
3647
- callback.call(binding, key, relationshipDefs[key]);
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
- eachTransformedAttribute(callback, binding) {
3651
- const attrDefs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({
3652
- type: this.modelName
3653
- });
3654
- Object.keys(attrDefs).forEach(key => {
3655
- if (attrDefs[key].type) {
3656
- callback.call(binding, key, attrDefs[key].type);
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
- @module @ember-data/store
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
- A `PromiseArray` is an object that acts like both an `Ember.Array`
3671
- and a promise. When the promise is resolved the resulting value
3672
- will be set to the `PromiseArray`'s `content` property. This makes
3673
- it easy to create data bindings with the `PromiseArray` that will be
3674
- updated when the promise resolves.
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
- This class should not be imported and instantiated directly.
2472
+ // Relationships
2473
+ // =============
3677
2474
 
3678
- For more information see the [Ember.PromiseProxyMixin
3679
- documentation](/ember/release/classes/PromiseProxyMixin).
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
- Example
2488
+ // Resource State
2489
+ // ===============
3682
2490
 
3683
- ```javascript
3684
- let promiseArray = PromiseArray.create({
3685
- promise: $.getJSON('/some/remote/data.json')
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
- promiseArray.length; // 0
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
- promiseArray.then(function() {
3691
- promiseArray.length; // 100
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
- @class PromiseArray
3696
- @public
3697
- @extends Ember.ArrayProxy
3698
- @uses Ember.PromiseProxyMixin
3699
- */
3700
- let PromiseArray = (_dec = reads('content.meta'), (_class$1 = class PromiseArray extends PromiseArrayProxy {
3701
- constructor(...args) {
3702
- super(...args);
3703
- _initializerDefineProperty(this, "meta", _descriptor$1, this);
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
- // constructor is accessed in some internals but not including it in the copyright for the deprecation
3723
- const ALLOWABLE_METHODS = ['constructor', 'then', 'catch', 'finally'];
3724
- const ALLOWABLE_PROPS = ['__ec_yieldable__', '__ec_cancel__'];
3725
- const PROXIED_ARRAY_PROPS = ['length', '[]', 'firstObject', 'lastObject', 'meta', 'content', 'isPending', 'isSettled', 'isRejected', 'isFulfilled', 'promise', 'reason'];
3726
- const PROXIED_OBJECT_PROPS = ['content', 'isPending', 'isSettled', 'isRejected', 'isFulfilled', 'promise', 'reason'];
3727
- function promiseArray(promise) {
3728
- const promiseObjectProxy = _promiseArray(promise);
3729
- if (macroCondition(!getOwnConfig().env.DEBUG)) {
3730
- return promiseObjectProxy;
3731
- }
3732
- const handler = {
3733
- get(target, prop, receiver) {
3734
- if (typeof prop === 'symbol') {
3735
- return Reflect.get(target, prop, receiver);
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().deprecations.DEPRECATE_A_USAGE)) {
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 {PromiseArray} promise
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(recordOrPromiseRecord) {
4586
- if (!recordOrPromiseRecord) {
2981
+ function extractIdentifierFromRecord$1(record) {
2982
+ if (!record) {
4587
2983
  return null;
4588
2984
  }
4589
- if (isPromiseRecord$1(recordOrPromiseRecord)) {
4590
- let content = recordOrPromiseRecord.content;
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 = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._instanceCache.getResourceCache(identifier) : this.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$1(modelName);
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$1(modelName);
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 = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._instanceCache.getResourceCache(identifier) : this.cache;
5704
- const createOptions = normalizeProperties(this, identifier, properties, cache.managedVersion === '1');
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 = identifier && (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._instanceCache.peek({
5731
- identifier,
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$1(resource);
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$1(resource);
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$1(identifier);
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$1(modelName),
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$1(modelName),
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$1(modelName),
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$1(modelName);
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$1(modelName);
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
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA)) {
6867
- ret = legacyCachePut(this, {
6868
- content: jsonApiDoc
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$1(modelName);
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 = identifier && (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._instanceCache.peek({
6973
- identifier,
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}`, cache && this._instanceCache.recordIsLoaded(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 SingletonCacheManager(cache);
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$1(modelName);
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$1(modelName);
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$1(modelName);
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, isForV1 = false) {
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], isForV1);
5569
+ relationshipValue = extractIdentifiersFromRecords(properties[prop]);
7289
5570
  } else {
7290
- relationshipValue = extractIdentifierFromRecord(properties[prop], isForV1);
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, isForV1 = false) {
7313
- return records.map(record => extractIdentifierFromRecord(record, isForV1));
5593
+ function extractIdentifiersFromRecords(records) {
5594
+ return records.map(record => extractIdentifierFromRecord(record));
7314
5595
  }
7315
- function extractIdentifierFromRecord(recordOrPromiseRecord, isForV1 = false) {
5596
+ function extractIdentifierFromRecord(recordOrPromiseRecord) {
7316
5597
  if (!recordOrPromiseRecord) {
7317
5598
  return null;
7318
5599
  }
7319
- const extract = isForV1 ? peekCache : recordIdentifierFor;
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
- function normalizeModelName(modelName) {
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 };