@ember-data/store 4.12.0-beta.7 → 4.12.0-beta.9

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.
@@ -35,6 +35,347 @@ import ObjectProxy from '@ember/object/proxy';
35
35
  function normalizeModelName$1(modelName) {
36
36
  return dasherize(modelName);
37
37
  }
38
+ function _initializerDefineProperty(target, property, descriptor, context) {
39
+ if (!descriptor) return;
40
+ Object.defineProperty(target, property, {
41
+ enumerable: descriptor.enumerable,
42
+ configurable: descriptor.configurable,
43
+ writable: descriptor.writable,
44
+ value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
45
+ });
46
+ }
47
+ function _classPrivateFieldBase(receiver, privateKey) {
48
+ if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
49
+ throw new TypeError("attempted to use private field on non-instance");
50
+ }
51
+ return receiver;
52
+ }
53
+ var id = 0;
54
+ function _classPrivateFieldKey(name) {
55
+ return "__private_" + id++ + "_" + name;
56
+ }
57
+ function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
58
+ var desc = {};
59
+ Object.keys(descriptor).forEach(function (key) {
60
+ desc[key] = descriptor[key];
61
+ });
62
+ desc.enumerable = !!desc.enumerable;
63
+ desc.configurable = !!desc.configurable;
64
+ if ('value' in desc || desc.initializer) {
65
+ desc.writable = true;
66
+ }
67
+ desc = decorators.slice().reverse().reduce(function (desc, decorator) {
68
+ return decorator(target, property, desc) || desc;
69
+ }, desc);
70
+ if (context && desc.initializer !== void 0) {
71
+ desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
72
+ desc.initializer = undefined;
73
+ }
74
+ if (desc.initializer === void 0) {
75
+ Object.defineProperty(target, property, desc);
76
+ desc = null;
77
+ }
78
+ return desc;
79
+ }
80
+ var _class$3, _descriptor$3, _descriptor2$1, _descriptor3, _descriptor4, _store$1, _request;
81
+ function urlFromLink(link) {
82
+ if (typeof link === 'string') return link;
83
+ return link.href;
84
+ }
85
+ let Document = (_class$3 = (_store$1 = /*#__PURE__*/_classPrivateFieldKey("store"), _request = /*#__PURE__*/_classPrivateFieldKey("request"), class Document {
86
+ constructor(store, identifier) {
87
+ Object.defineProperty(this, _request, {
88
+ value: _request2
89
+ });
90
+ _initializerDefineProperty(this, "links", _descriptor$3, this);
91
+ _initializerDefineProperty(this, "data", _descriptor2$1, this);
92
+ _initializerDefineProperty(this, "errors", _descriptor3, this);
93
+ _initializerDefineProperty(this, "meta", _descriptor4, this);
94
+ Object.defineProperty(this, _store$1, {
95
+ writable: true,
96
+ value: void 0
97
+ });
98
+ _classPrivateFieldBase(this, _store$1)[_store$1] = store;
99
+ this.identifier = identifier;
100
+ }
101
+ fetch(options = {}) {
102
+ assert(`No self link`, this.links?.self);
103
+ options.cacheOptions = options.cacheOptions || {};
104
+ options.cacheOptions.key = this.identifier?.lid;
105
+ return _classPrivateFieldBase(this, _request)[_request]('self', options);
106
+ }
107
+ next(options) {
108
+ return _classPrivateFieldBase(this, _request)[_request]('next', options);
109
+ }
110
+ prev(options) {
111
+ return _classPrivateFieldBase(this, _request)[_request]('prev', options);
112
+ }
113
+ first(options) {
114
+ return _classPrivateFieldBase(this, _request)[_request]('first', options);
115
+ }
116
+ last(options) {
117
+ return _classPrivateFieldBase(this, _request)[_request]('last', options);
118
+ }
119
+ toJSON() {
120
+ const data = {};
121
+ data.identifier = this.identifier;
122
+ if (this.data !== undefined) {
123
+ data.data = this.data;
124
+ }
125
+ if (this.links !== undefined) {
126
+ data.links = this.links;
127
+ }
128
+ if (this.errors !== undefined) {
129
+ data.errors = this.errors;
130
+ }
131
+ if (this.meta !== undefined) {
132
+ data.meta = this.meta;
133
+ }
134
+ return data;
135
+ }
136
+ }), (_descriptor$3 = _applyDecoratedDescriptor(_class$3.prototype, "links", [tracked], {
137
+ configurable: true,
138
+ enumerable: true,
139
+ writable: true,
140
+ initializer: null
141
+ }), _descriptor2$1 = _applyDecoratedDescriptor(_class$3.prototype, "data", [tracked], {
142
+ configurable: true,
143
+ enumerable: true,
144
+ writable: true,
145
+ initializer: null
146
+ }), _descriptor3 = _applyDecoratedDescriptor(_class$3.prototype, "errors", [tracked], {
147
+ configurable: true,
148
+ enumerable: true,
149
+ writable: true,
150
+ initializer: null
151
+ }), _descriptor4 = _applyDecoratedDescriptor(_class$3.prototype, "meta", [tracked], {
152
+ configurable: true,
153
+ enumerable: true,
154
+ writable: true,
155
+ initializer: null
156
+ })), _class$3);
157
+ async function _request2(link, options = {}) {
158
+ const href = this.links?.[link];
159
+ if (!href) {
160
+ return null;
161
+ }
162
+ const response = await _classPrivateFieldBase(this, _store$1)[_store$1].request(Object.assign(options, {
163
+ url: urlFromLink(href)
164
+ }));
165
+ return response.content;
166
+ }
167
+ function isErrorDocument(document) {
168
+ return 'errors' in document;
169
+ }
170
+ function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
171
+ const {
172
+ identifier
173
+ } = options;
174
+ if (isErrorDocument(document)) {
175
+ if (!identifier && !options.shouldHydrate) {
176
+ return document;
177
+ }
178
+ let doc;
179
+ if (identifier) {
180
+ doc = store._documentCache.get(identifier);
181
+ }
182
+ if (!doc) {
183
+ doc = new Document(store, identifier);
184
+ copyDocumentProperties(doc, document);
185
+ if (identifier) {
186
+ store._documentCache.set(identifier, doc);
187
+ }
188
+ } else if (!isFromCache) {
189
+ doc.data = undefined;
190
+ copyDocumentProperties(doc, document);
191
+ }
192
+ return options.shouldHydrate ? doc : document;
193
+ }
194
+ if (Array.isArray(document.data)) {
195
+ const {
196
+ recordArrayManager
197
+ } = store;
198
+ if (!identifier) {
199
+ if (!options.shouldHydrate) {
200
+ return document;
201
+ }
202
+ const data = recordArrayManager.createArray({
203
+ identifiers: document.data,
204
+ doc: document,
205
+ query: request
206
+ });
207
+ const doc = new Document(store, null);
208
+ doc.data = data;
209
+ doc.meta = document.meta;
210
+ doc.links = document.links;
211
+ return doc;
212
+ }
213
+ let managed = recordArrayManager._keyedArrays.get(identifier.lid);
214
+ if (!managed) {
215
+ managed = recordArrayManager.createArray({
216
+ identifiers: document.data,
217
+ doc: document
218
+ });
219
+ recordArrayManager._keyedArrays.set(identifier.lid, managed);
220
+ const doc = new Document(store, identifier);
221
+ doc.data = managed;
222
+ doc.meta = document.meta;
223
+ doc.links = document.links;
224
+ store._documentCache.set(identifier, doc);
225
+ return options.shouldHydrate ? doc : document;
226
+ } else {
227
+ const doc = store._documentCache.get(identifier);
228
+ if (!isFromCache) {
229
+ recordArrayManager.populateManagedArray(managed, document.data, document);
230
+ doc.data = managed;
231
+ doc.meta = document.meta;
232
+ doc.links = document.links;
233
+ }
234
+ return options.shouldHydrate ? doc : document;
235
+ }
236
+ } else {
237
+ if (!identifier && !options.shouldHydrate) {
238
+ return document;
239
+ }
240
+ const data = document.data ? store.peekRecord(document.data) : null;
241
+ let doc;
242
+ if (identifier) {
243
+ doc = store._documentCache.get(identifier);
244
+ }
245
+ if (!doc) {
246
+ doc = new Document(store, identifier);
247
+ doc.data = data;
248
+ copyDocumentProperties(doc, document);
249
+ if (identifier) {
250
+ store._documentCache.set(identifier, doc);
251
+ }
252
+ } else if (!isFromCache) {
253
+ doc.data = data;
254
+ copyDocumentProperties(doc, document);
255
+ }
256
+ return options.shouldHydrate ? doc : document;
257
+ }
258
+ }
259
+ function calcShouldFetch(store, request, hasCachedValue, identifier) {
260
+ const {
261
+ cacheOptions
262
+ } = request;
263
+ return cacheOptions?.reload || !hasCachedValue || (store.lifetimes && identifier ? store.lifetimes.isHardExpired(identifier) : false);
264
+ }
265
+ function calcShouldBackgroundFetch(store, request, willFetch, identifier) {
266
+ const {
267
+ cacheOptions
268
+ } = request;
269
+ return !willFetch && (cacheOptions?.backgroundReload || (store.lifetimes && identifier ? store.lifetimes.isSoftExpired(identifier) : false));
270
+ }
271
+ function fetchContentAndHydrate(next, context, identifier, shouldFetch, shouldBackgroundFetch) {
272
+ const {
273
+ store
274
+ } = context.request;
275
+ const shouldHydrate = context.request[Symbol.for('ember-data:enable-hydration')] || false;
276
+ return next(context.request).then(document => {
277
+ store.requestManager._pending.delete(context.id);
278
+ store._enableAsyncFlush = true;
279
+ let response;
280
+ store._join(() => {
281
+ response = store.cache.put(document);
282
+ response = maybeUpdateUiObjects(store, context.request, {
283
+ shouldHydrate,
284
+ shouldFetch,
285
+ shouldBackgroundFetch,
286
+ identifier
287
+ }, response, false);
288
+ });
289
+ store._enableAsyncFlush = null;
290
+ if (shouldFetch) {
291
+ return response;
292
+ } else if (shouldBackgroundFetch) {
293
+ store.notifications._flush();
294
+ }
295
+ }, error => {
296
+ store.requestManager._pending.delete(context.id);
297
+ if (context.request.signal?.aborted) {
298
+ throw error;
299
+ }
300
+ store.requestManager._pending.delete(context.id);
301
+ store._enableAsyncFlush = true;
302
+ let response;
303
+ store._join(() => {
304
+ response = store.cache.put(error);
305
+ response = maybeUpdateUiObjects(store, context.request, {
306
+ shouldHydrate,
307
+ shouldFetch,
308
+ shouldBackgroundFetch,
309
+ identifier
310
+ }, response, false);
311
+ });
312
+ store._enableAsyncFlush = null;
313
+ if (!shouldBackgroundFetch) {
314
+ const newError = cloneError(error);
315
+ newError.content = response;
316
+ throw newError;
317
+ } else {
318
+ store.notifications._flush();
319
+ }
320
+ });
321
+ }
322
+ function cloneError(error) {
323
+ const cloned = new Error(error.message);
324
+ cloned.stack = error.stack;
325
+ cloned.error = error.error;
326
+ return cloned;
327
+ }
328
+ const SkipCache = Symbol.for('ember-data:skip-cache');
329
+ const EnableHydration = Symbol.for('ember-data:enable-hydration');
330
+ const CacheHandler = {
331
+ request(context, next) {
332
+ // if we have no cache or no cache-key skip cache handling
333
+ if (!context.request.store || context.request.cacheOptions?.[SkipCache]) {
334
+ return next(context.request);
335
+ }
336
+ const {
337
+ store
338
+ } = context.request;
339
+ const identifier = store.identifierCache.getOrCreateDocumentIdentifier(context.request);
340
+ const peeked = identifier ? store.cache.peekRequest(identifier) : null;
341
+
342
+ // determine if we should skip cache
343
+ if (calcShouldFetch(store, context.request, !!peeked, identifier)) {
344
+ return fetchContentAndHydrate(next, context, identifier, true, false);
345
+ }
346
+
347
+ // if we have not skipped cache, determine if we should update behind the scenes
348
+ if (calcShouldBackgroundFetch(store, context.request, false, identifier)) {
349
+ let promise = fetchContentAndHydrate(next, context, identifier, false, true);
350
+ store.requestManager._pending.set(context.id, promise);
351
+ }
352
+ const shouldHydrate = context.request[EnableHydration] || false;
353
+ if ('error' in peeked) {
354
+ const content = shouldHydrate ? maybeUpdateUiObjects(store, context.request, {
355
+ shouldHydrate,
356
+ identifier
357
+ }, peeked.content, true) : peeked.content;
358
+ const newError = cloneError(peeked);
359
+ newError.content = content;
360
+ throw newError;
361
+ }
362
+ return Promise.resolve(shouldHydrate ? maybeUpdateUiObjects(store, context.request, {
363
+ shouldHydrate,
364
+ identifier
365
+ }, peeked.content, true) : peeked.content);
366
+ }
367
+ };
368
+ function copyDocumentProperties(target, source) {
369
+ if ('links' in source) {
370
+ target.links = source.links;
371
+ }
372
+ if ('meta' in source) {
373
+ target.meta = source.meta;
374
+ }
375
+ if ('errors' in source) {
376
+ target.errors = source.errors;
377
+ }
378
+ }
38
379
 
39
380
  /*
40
381
  * Returns the Cache instance associated with a given
@@ -145,9 +486,13 @@ function installPolyfill() {
145
486
  @module @ember-data/store
146
487
  */
147
488
  const IDENTIFIERS = new Set();
489
+ const DOCUMENTS = new Set();
148
490
  function isStableIdentifier(identifier) {
149
491
  return IDENTIFIERS.has(identifier);
150
492
  }
493
+ function isDocumentIdentifier(identifier) {
494
+ return DOCUMENTS.has(identifier);
495
+ }
151
496
  const isFastBoot = typeof FastBoot !== 'undefined';
152
497
  const _crypto = isFastBoot ? FastBoot.require('crypto') : window.crypto;
153
498
  if (macroCondition(getOwnConfig().polyfillUUID)) {
@@ -180,20 +525,31 @@ function setIdentifierResetMethod(method) {
180
525
  configuredResetMethod = method;
181
526
  }
182
527
  function defaultGenerationMethod(data, bucket) {
183
- if (isNonEmptyString(data.lid)) {
184
- return data.lid;
185
- }
186
- if (data.id !== undefined) {
187
- let {
188
- type,
189
- id
190
- } = data;
191
- // TODO: add test for id not a string
192
- if (isNonEmptyString(coerceId(id))) {
193
- return `@lid:${normalizeModelName$1(type)}-${id}`;
528
+ if (bucket === 'record') {
529
+ if (isNonEmptyString(data.lid)) {
530
+ return data.lid;
531
+ }
532
+ if (data.id !== undefined) {
533
+ let {
534
+ type,
535
+ id
536
+ } = data;
537
+ // TODO: add test for id not a string
538
+ if (isNonEmptyString(coerceId(id))) {
539
+ return `@lid:${normalizeModelName$1(type)}-${id}`;
540
+ }
541
+ }
542
+ return uuidv4();
543
+ } else if (bucket === 'document') {
544
+ if (!data.url) {
545
+ return null;
194
546
  }
547
+ if (!data.method || data.method.toUpperCase() === 'GET') {
548
+ return data.url;
549
+ }
550
+ return null;
195
551
  }
196
- return uuidv4();
552
+ assert(`Unknown bucket ${bucket}`, false);
197
553
  }
198
554
  function defaultEmptyCallback(...args) {}
199
555
  let DEBUG_MAP;
@@ -218,7 +574,8 @@ class IdentifierCache {
218
574
  constructor() {
219
575
  this._cache = {
220
576
  lids: new Map(),
221
- types: Object.create(null)
577
+ types: Object.create(null),
578
+ documents: new Map()
222
579
  };
223
580
  // we cache the user configuredGenerationMethod at init because it must
224
581
  // be configured prior and is not allowed to be changed
@@ -392,6 +749,36 @@ class IdentifierCache {
392
749
  return this._getRecordIdentifier(resource, false);
393
750
  }
394
751
 
752
+ /**
753
+ Returns the DocumentIdentifier for the given Request, creates one if it does not yet exist.
754
+ Returns `null` if the request does not have a `cacheKey` or `url`.
755
+ @method getOrCreateDocumentIdentifier
756
+ @param request
757
+ @returns {StableDocumentIdentifier | null}
758
+ @public
759
+ */
760
+ getOrCreateDocumentIdentifier(request) {
761
+ let cacheKey = request.cacheOptions?.key;
762
+ if (!cacheKey) {
763
+ cacheKey = this._generate(request, 'document');
764
+ }
765
+ if (!cacheKey) {
766
+ return null;
767
+ }
768
+ let identifier = this._cache.documents.get(cacheKey);
769
+ if (identifier === undefined) {
770
+ identifier = {
771
+ lid: cacheKey
772
+ };
773
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
774
+ Object.freeze(identifier);
775
+ }
776
+ DOCUMENTS.add(identifier);
777
+ this._cache.documents.set(cacheKey, identifier);
778
+ }
779
+ return identifier;
780
+ }
781
+
395
782
  /**
396
783
  Returns the Identifier for the given Resource, creates one if it does not yet exist.
397
784
  Specifically this means that we:
@@ -559,6 +946,9 @@ class IdentifierCache {
559
946
  }
560
947
  }
561
948
  destroy() {
949
+ this._cache.documents.forEach(identifier => {
950
+ DOCUMENTS.delete(identifier);
951
+ });
562
952
  this._reset();
563
953
  }
564
954
  }
@@ -694,38 +1084,6 @@ function detectMerge(typesCache, identifier, data, newId, lids) {
694
1084
  }
695
1085
  return false;
696
1086
  }
697
- function _initializerDefineProperty(target, property, descriptor, context) {
698
- if (!descriptor) return;
699
- Object.defineProperty(target, property, {
700
- enumerable: descriptor.enumerable,
701
- configurable: descriptor.configurable,
702
- writable: descriptor.writable,
703
- value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
704
- });
705
- }
706
- function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
707
- var desc = {};
708
- Object.keys(descriptor).forEach(function (key) {
709
- desc[key] = descriptor[key];
710
- });
711
- desc.enumerable = !!desc.enumerable;
712
- desc.configurable = !!desc.configurable;
713
- if ('value' in desc || desc.initializer) {
714
- desc.writable = true;
715
- }
716
- desc = decorators.slice().reverse().reduce(function (desc, decorator) {
717
- return decorator(target, property, desc) || desc;
718
- }, desc);
719
- if (context && desc.initializer !== void 0) {
720
- desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
721
- desc.initializer = undefined;
722
- }
723
- if (desc.initializer === void 0) {
724
- Object.defineProperty(target, property, desc);
725
- desc = null;
726
- }
727
- return desc;
728
- }
729
1087
  let tokenId = 0;
730
1088
  const CacheOperations = new Set(['added', 'removed', 'state', 'updated']);
731
1089
  function isCacheOperationValue(value) {
@@ -753,16 +1111,12 @@ function unsubscribe(token) {
753
1111
  }
754
1112
  }
755
1113
 
756
- /*
757
- Currently only support a single callback per identifier
758
- */
759
-
760
1114
  /**
761
1115
  * The NotificationManager provides the ability to subscribe to
762
1116
  * changes to Cache state.
763
1117
  *
764
1118
  * This Feature is what allows EmberData to create subscriptions that
765
- * work with any framework or change notification system.
1119
+ * work with any framework or change-notification system.
766
1120
  *
767
1121
  * @class NotificationManager
768
1122
  * @public
@@ -776,24 +1130,35 @@ class NotificationManager {
776
1130
  }
777
1131
 
778
1132
  /**
779
- * Subscribe to changes for a given resource identifier
1133
+ * Subscribe to changes for a given resource identifier, resource addition/removal, or document addition/removal.
780
1134
  *
781
1135
  * ```ts
782
- * interface NotificationCallback {
1136
+ * export type CacheOperation = 'added' | 'removed' | 'updated' | 'state';
1137
+ *
1138
+ * export interface NotificationCallback {
783
1139
  * (identifier: StableRecordIdentifier, notificationType: 'attributes' | 'relationships', key?: string): void;
784
1140
  * (identifier: StableRecordIdentifier, notificationType: 'errors' | 'meta' | 'identity' | 'state'): void;
785
1141
  * (identifier: StableRecordIdentifier, notificationType: NotificationType, key?: string): void;
786
1142
  * }
1143
+ * export interface ResourceOperationCallback {
1144
+ * // resource updates
1145
+ * (identifier: StableRecordIdentifier, notificationType: CacheOperation): void;
1146
+ * }
1147
+ * export interface DocumentOperationCallback {
1148
+ * // document updates
1149
+ * (identifier: StableDocumentIdentifier, notificationType: CacheOperation): void;
1150
+ * }
787
1151
  * ```
788
1152
  *
789
1153
  * @method subscribe
790
1154
  * @public
791
- * @param {StableRecordIdentifier} identifier
792
- * @param {NotificationCallback} callback
1155
+ * @param {StableDocumentIdentifier | StableRecordIdentifier | 'resource' | 'document'} identifier
1156
+ * @param {NotificationCallback | ResourceOperationCallback | DocumentOperationCallback} callback
793
1157
  * @returns {UnsubscribeToken} an opaque token to be used with unsubscribe
794
1158
  */
1159
+
795
1160
  subscribe(identifier, callback) {
796
- assert(`Expected to receive a stable Identifier to subscribe to`, identifier === 'resource' || identifier === 'document' || isStableIdentifier(identifier));
1161
+ assert(`Expected to receive a stable Identifier to subscribe to`, identifier === 'resource' || identifier === 'document' || isStableIdentifier(identifier) || isDocumentIdentifier(identifier));
797
1162
  let map = Cache.get(identifier);
798
1163
  if (!map) {
799
1164
  map = new Map();
@@ -833,7 +1198,7 @@ class NotificationManager {
833
1198
 
834
1199
  notify(identifier, value, key) {
835
1200
  assert(`Notify does not accept a key argument for the namespace '${value}'. Received key '${key || ''}'.`, !key || value === 'attributes' || value === 'relationships');
836
- if (!isStableIdentifier(identifier)) {
1201
+ if (!isStableIdentifier(identifier) && !isDocumentIdentifier(identifier)) {
837
1202
  if (macroCondition(getOwnConfig().debug.LOG_NOTIFICATIONS)) {
838
1203
  // eslint-disable-next-line no-console
839
1204
  console.log(`Notifying: Expected to receive a stable Identifier to notify '${value}' '${key || ''}' with, but ${String(identifier)} is not in the cache`, identifier);
@@ -842,7 +1207,7 @@ class NotificationManager {
842
1207
  }
843
1208
  if (macroCondition(getOwnConfig().debug.LOG_NOTIFICATIONS)) {
844
1209
  // eslint-disable-next-line no-console
845
- console.log(`Buffering Notify: ${String(identifier)}\t${value}\t${key || ''}`);
1210
+ console.log(`Buffering Notify: ${String(identifier.lid)}\t${value}\t${key || ''}`);
846
1211
  }
847
1212
  const hasSubscribers = Boolean(Cache.get(identifier)?.size);
848
1213
  if (isCacheOperationValue(value) || hasSubscribers) {
@@ -894,7 +1259,7 @@ class NotificationManager {
894
1259
 
895
1260
  // TODO for documents this will need to switch based on Identifier kind
896
1261
  if (isCacheOperationValue(value)) {
897
- let callbackMap = Cache.get('resource');
1262
+ let callbackMap = Cache.get(isDocumentIdentifier(identifier) ? 'document' : 'resource');
898
1263
  if (callbackMap) {
899
1264
  callbackMap.forEach(cb => {
900
1265
  cb(identifier, value);
@@ -1111,16 +1476,6 @@ let RecordReference = (_class$2 = class RecordReference {
1111
1476
  return 0;
1112
1477
  }
1113
1478
  }), _class$2);
1114
- function _classPrivateFieldBase(receiver, privateKey) {
1115
- if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
1116
- throw new TypeError("attempted to use private field on non-instance");
1117
- }
1118
- return receiver;
1119
- }
1120
- var id = 0;
1121
- function _classPrivateFieldKey(name) {
1122
- return "__private_" + id++ + "_" + name;
1123
- }
1124
1479
  function legacyCachePut(store, doc) {
1125
1480
  const jsonApiDoc = doc.content;
1126
1481
  let ret;
@@ -1242,7 +1597,6 @@ class NonSingletonCacheManager {
1242
1597
  }
1243
1598
  // Cache Management
1244
1599
  // ================
1245
-
1246
1600
  /**
1247
1601
  * Cache the response to a request
1248
1602
  *
@@ -2273,7 +2627,7 @@ class LegacyWrapper {
2273
2627
  });
2274
2628
  }
2275
2629
  notifyChange(identifier, namespace, key) {
2276
- assert(`Expected a stable identifier`, isStableIdentifier(identifier));
2630
+ assert(`Expected a stable identifier`, isStableIdentifier(identifier) || isDocumentIdentifier(identifier));
2277
2631
 
2278
2632
  // TODO do we still get value from this?
2279
2633
  if (namespace === 'relationships' && key) {
@@ -2420,7 +2774,7 @@ class LegacyWrapper {
2420
2774
  assert(`Expected a stable identifier`, isStableIdentifier(type));
2421
2775
  identifier = type;
2422
2776
  }
2423
- const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_CREATE_RECORD_DATA_FOR_HOOK) ? this._store._instanceCache.getResourceCache(identifier) : this._store.cache;
2777
+ const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._store._instanceCache.getResourceCache(identifier) : this._store.cache;
2424
2778
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1CACHE_STORE_APIS)) {
2425
2779
  if (!id && !lid && typeof type === 'string') {
2426
2780
  cache.clientDidCreate(identifier);
@@ -2540,7 +2894,7 @@ class V2CacheStoreWrapper {
2540
2894
  });
2541
2895
  }
2542
2896
  notifyChange(identifier, namespace, key) {
2543
- assert(`Expected a stable identifier`, isStableIdentifier(identifier));
2897
+ assert(`Expected a stable identifier`, isStableIdentifier(identifier) || isDocumentIdentifier(identifier));
2544
2898
 
2545
2899
  // TODO do we still get value from this?
2546
2900
  if (namespace === 'relationships' && key) {
@@ -2555,7 +2909,7 @@ class V2CacheStoreWrapper {
2555
2909
  return this._store.getSchemaDefinitionService();
2556
2910
  }
2557
2911
  recordDataFor(identifier) {
2558
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_CREATE_RECORD_DATA_FOR_HOOK)) {
2912
+ if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA)) {
2559
2913
  deprecate(`StoreWrapper.recordDataFor is deprecated. With Singleton Cache, this method is no longer needed as the caller is its own cache reference.`, false, {
2560
2914
  for: '@ember-data/store',
2561
2915
  id: 'ember-data:deprecate-record-data-for',
@@ -2567,7 +2921,7 @@ class V2CacheStoreWrapper {
2567
2921
  });
2568
2922
  }
2569
2923
  assert(`Expected a stable identifier`, isStableIdentifier(identifier));
2570
- return macroCondition(getOwnConfig().deprecations.DEPRECATE_CREATE_RECORD_DATA_FOR_HOOK) ? this._store._instanceCache.getResourceCache(identifier) : void 0;
2924
+ return macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._store._instanceCache.getResourceCache(identifier) : void 0;
2571
2925
  }
2572
2926
  setRecordId(identifier, id) {
2573
2927
  assert(`Expected a stable identifier`, isStableIdentifier(identifier));
@@ -2660,7 +3014,7 @@ class InstanceCache {
2660
3014
  };
2661
3015
  this.store = store;
2662
3016
  this._storeWrapper = new CacheStoreWrapper(this.store);
2663
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_CREATE_RECORD_DATA_FOR_HOOK)) {
3017
+ if (macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA)) {
2664
3018
  this.__cacheFor = resource => {
2665
3019
  // TODO enforce strict
2666
3020
  const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resource);
@@ -2701,7 +3055,7 @@ class InstanceCache {
2701
3055
  record: staleIdentifier,
2702
3056
  value: keptIdentifier
2703
3057
  });
2704
- } else if (macroCondition(!getOwnConfig().deprecations.DEPRECATE_CREATE_RECORD_DATA_FOR_HOOK)) {
3058
+ } else if (macroCondition(!getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA)) {
2705
3059
  this.store.cache.patch({
2706
3060
  op: 'mergeIdentifiers',
2707
3061
  record: staleIdentifier,
@@ -3343,7 +3697,6 @@ var _dec, _class$1, _descriptor$1;
3343
3697
  @extends Ember.ArrayProxy
3344
3698
  @uses Ember.PromiseProxyMixin
3345
3699
  */
3346
-
3347
3700
  let PromiseArray = (_dec = reads('content.meta'), (_class$1 = class PromiseArray extends PromiseArrayProxy {
3348
3701
  constructor(...args) {
3349
3702
  super(...args);
@@ -3483,6 +3836,10 @@ function convertToInt(prop) {
3483
3836
  return num % 1 === 0 ? num : null;
3484
3837
  }
3485
3838
  let Tag = (_class = class Tag {
3839
+ /*
3840
+ * whether this was part of a transaction when last mutated
3841
+ */
3842
+
3486
3843
  constructor() {
3487
3844
  _initializerDefineProperty(this, "ref", _descriptor, this);
3488
3845
  this.shouldReset = false;
@@ -3557,6 +3914,22 @@ let IdentifierArray = (_class3 = class IdentifierArray {
3557
3914
  [NOTIFY]() {
3558
3915
  notifyArray(this);
3559
3916
  }
3917
+
3918
+ /**
3919
+ The modelClass represented by this record array.
3920
+ @property type
3921
+ @public
3922
+ @deprecated
3923
+ @type {subclass of Model}
3924
+ */
3925
+
3926
+ /**
3927
+ The store that created this record array.
3928
+ @property store
3929
+ @private
3930
+ @type Store
3931
+ */
3932
+
3560
3933
  destroy() {
3561
3934
  this.isDestroying = true;
3562
3935
  // changing the reference breaks the Proxy
@@ -4555,12 +4928,23 @@ function sync(array, changes) {
4555
4928
  }
4556
4929
  }
4557
4930
 
4931
+ /**
4932
+ * @module @ember-data/store
4933
+ */
4558
4934
  const Touching = Symbol('touching');
4559
4935
  const RequestPromise = Symbol('promise');
4560
4936
  function hasRecordIdentifier(op) {
4561
4937
  return 'recordIdentifier' in op;
4562
4938
  }
4563
- class RequestCache {
4939
+
4940
+ /**
4941
+ * The RequestStateService is used to track the state of requests
4942
+ * for fetching or updating known resource identifies that are inflight.
4943
+ *
4944
+ * @class RequestStateService
4945
+ * @public
4946
+ */
4947
+ class RequestStateService {
4564
4948
  constructor(store) {
4565
4949
  this._pending = Object.create(null);
4566
4950
  this._done = new Map();
@@ -4572,7 +4956,7 @@ class RequestCache {
4572
4956
  _clearEntries(identifier) {
4573
4957
  this._done.delete(identifier);
4574
4958
  }
4575
- enqueue(promise, queryRequest) {
4959
+ _enqueue(promise, queryRequest) {
4576
4960
  let query = queryRequest.data[0];
4577
4961
  if (hasRecordIdentifier(query)) {
4578
4962
  let lid = query.recordIdentifier.lid;
@@ -4671,18 +5055,66 @@ class RequestCache {
4671
5055
  this._done.set(identifier, requests);
4672
5056
  });
4673
5057
  }
5058
+
5059
+ /**
5060
+ * Subscribe to requests for a given resource identity.
5061
+ *
5062
+ * The callback will receive the current state of the request.
5063
+ *
5064
+ * ```ts
5065
+ * interface RequestState {
5066
+ * state: 'pending' | 'fulfilled' | 'rejected';
5067
+ * type: 'query' | 'mutation';
5068
+ * request: Request;
5069
+ * response?: { data: unknown };
5070
+ * }
5071
+ * ```
5072
+ *
5073
+ * Note: It should be considered dangerous to use this API for more than simple
5074
+ * state derivation or debugging. The `request` and `response` properties are poorly
5075
+ * spec'd and may change unexpectedly when shifting what Handlers are in use or how
5076
+ * requests are issued from the Store.
5077
+ *
5078
+ * We expect to revisit this API in the near future as we continue to refine the
5079
+ * RequestManager ergonomics, as a simpler but more powerful direct integration
5080
+ * with the RequestManager for these purposes is likely to be a better long-term
5081
+ * design.
5082
+ *
5083
+ * @method subscribeForRecord
5084
+ * @public
5085
+ * @param {StableRecordIdentifier} identifier
5086
+ * @param {(state: RequestState) => void} callback
5087
+ */
4674
5088
  subscribeForRecord(identifier, callback) {
4675
5089
  if (!this._subscriptions[identifier.lid]) {
4676
5090
  this._subscriptions[identifier.lid] = [];
4677
5091
  }
4678
5092
  this._subscriptions[identifier.lid].push(callback);
4679
5093
  }
5094
+
5095
+ /**
5096
+ * Retrieve all active requests for a given resource identity.
5097
+ *
5098
+ * @method getPendingRequestsForRecord
5099
+ * @public
5100
+ * @param {StableRecordIdentifier} identifier
5101
+ * @returns {RequestState[]} an array of request states for any pending requests for the given identifier
5102
+ */
4680
5103
  getPendingRequestsForRecord(identifier) {
4681
5104
  if (this._pending[identifier.lid]) {
4682
5105
  return this._pending[identifier.lid];
4683
5106
  }
4684
5107
  return [];
4685
5108
  }
5109
+
5110
+ /**
5111
+ * Retrieve the last completed request for a given resource identity.
5112
+ *
5113
+ * @method getLastRequestForRecord
5114
+ * @public
5115
+ * @param {StableRecordIdentifier} identifier
5116
+ * @returns {RequestState | null} the state of the most recent request for the given identifier
5117
+ */
4686
5118
  getLastRequestForRecord(identifier) {
4687
5119
  let requests = this._done.get(identifier);
4688
5120
  if (requests) {
@@ -4699,6 +5131,27 @@ class RequestCache {
4699
5131
  // hello world
4700
5132
 
4701
5133
  let _Cache;
5134
+
5135
+ /**
5136
+ * A Store coordinates interaction between your application, a [Cache](https://api.emberjs.com/ember-data/release/classes/%3CInterface%3E%20Cache),
5137
+ * and sources of data (such as your API or a local persistence layer)
5138
+ * accessed via a [RequestManager](https://github.com/emberjs/data/tree/main/packages/request).
5139
+ *
5140
+ * ```app/services/store.js
5141
+ * import Store from '@ember-data/store';
5142
+ *
5143
+ * export default class extends Store {}
5144
+ * ```
5145
+ *
5146
+ * Most Ember applications will only have a single `Store` configured as a Service
5147
+ * in this manner. However, setting up multiple stores is possible, including using
5148
+ * each as a unique service.
5149
+ *
5150
+
5151
+ @class Store
5152
+ @public
5153
+ */
5154
+
4702
5155
  class Store {
4703
5156
  /**
4704
5157
  * Provides access to the NotificationManager associated
@@ -4711,6 +5164,20 @@ class Store {
4711
5164
  * @public
4712
5165
  */
4713
5166
 
5167
+ /**
5168
+ * Provides access to the SchemaService instance
5169
+ * for this Store instance.
5170
+ *
5171
+ * The SchemaService can be used to query for
5172
+ * information about the schema of a resource.
5173
+ *
5174
+ * @property {SchemaService} schema
5175
+ * @public
5176
+ */
5177
+ get schema() {
5178
+ return this.getSchemaDefinitionService();
5179
+ }
5180
+
4714
5181
  /**
4715
5182
  * Provides access to the IdentifierCache instance
4716
5183
  * for this store.
@@ -4754,20 +5221,23 @@ class Store {
4754
5221
  * A Property which an App may set to provide a Lifetimes Service
4755
5222
  * to control when a cached request becomes stale.
4756
5223
  *
4757
- * Note, when defined, these methods will only be invoked if `key` `url` and `method`
4758
- * are all present.
5224
+ * Note, when defined, these methods will only be invoked if a
5225
+ * cache key exists for the request, either because the request
5226
+ * contains `cacheOptions.key` or because the [IdentifierCache](/ember-data/release/classes/IdentifierCache)
5227
+ * was able to generate a key for the request using the configured
5228
+ * [generation method](/ember-data/release/functions/@ember-data%2Fstore/setIdentifierGenerationMethod).
4759
5229
  *
4760
5230
  * `isSoftExpired` will only be invoked if `isHardExpired` returns `false`.
4761
5231
  *
4762
5232
  * ```ts
4763
5233
  * store.lifetimes = {
4764
5234
  * // make the request and ignore the current cache state
4765
- * isHardExpired(key: string, url: string, method?: HTTPMethod): boolean {
5235
+ * isHardExpired(identifier: StableDocumentIdentifier): boolean {
4766
5236
  * return false;
4767
5237
  * }
4768
5238
  *
4769
5239
  * // make the request in the background if true, return cache state
4770
- * isSoftExpired(key: string, url: string, method: HTTPMethod): boolean {
5240
+ * isSoftExpired(identifier: StableDocumentIdentifier): boolean {
4771
5241
  * return false;
4772
5242
  * }
4773
5243
  * }
@@ -4798,11 +5268,12 @@ class Store {
4798
5268
  });
4799
5269
 
4800
5270
  // private
4801
- this._requestCache = new RequestCache(this);
5271
+ this._requestCache = new RequestStateService(this);
4802
5272
  this._instanceCache = new InstanceCache(this);
4803
5273
  this._adapterCache = Object.create(null);
4804
5274
  this._serializerCache = Object.create(null);
4805
5275
  this._modelFactoryCache = Object.create(null);
5276
+ this._documentCache = new Map();
4806
5277
  }
4807
5278
  _run(cb) {
4808
5279
  assert(`EmberData should never encounter a nested run`, !this._cbs);
@@ -4854,6 +5325,7 @@ class Store {
4854
5325
  lids.forEach(lid => {
4855
5326
  all.push(...pending[lid].map(v => v[RequestPromise]));
4856
5327
  });
5328
+ this.requestManager._pending.forEach(v => all.push(v));
4857
5329
  const promise = Promise.allSettled(all);
4858
5330
  promise.length = all.length;
4859
5331
  return promise;
@@ -4888,10 +5360,9 @@ class Store {
4888
5360
  // we lazily set the cache handler when we issue the first request
4889
5361
  // because constructor doesn't allow for this to run after
4890
5362
  // the user has had the chance to set the prop.
4891
- const storeSymbol = Symbol.for('ember-data:enable-hydration');
4892
5363
  let opts = {
4893
5364
  store: this,
4894
- [storeSymbol]: true
5365
+ [EnableHydration]: true
4895
5366
  };
4896
5367
  if (macroCondition(getOwnConfig().env.TESTING)) {
4897
5368
  if (this.DISABLE_WAITER) {
@@ -4994,25 +5465,27 @@ class Store {
4994
5465
  */
4995
5466
  getSchemaDefinitionService() {
4996
5467
  if (macroCondition(getOwnConfig().packages.HAS_MODEL_PACKAGE)) {
4997
- if (!this._schemaDefinitionService) {
5468
+ if (!this._schema) {
4998
5469
  // it is potentially a mistake for the RFC to have not enabled chaining these services, though highlander rule is nice.
4999
5470
  // what ember-m3 did via private API to allow both worlds to interop would be much much harder using this.
5000
- this._schemaDefinitionService = new DSModelSchemaDefinitionService(this);
5471
+ this._schema = new DSModelSchemaDefinitionService(this);
5001
5472
  }
5002
5473
  }
5003
- assert(`You must registerSchemaDefinitionService with the store to use custom model classes`, this._schemaDefinitionService);
5004
- return this._schemaDefinitionService;
5474
+ assert(`You must registerSchemaDefinitionService with the store to use custom model classes`, this._schema);
5475
+ return this._schema;
5005
5476
  }
5006
5477
 
5007
5478
  /**
5008
- * Allows an app to register a custom SchemaDefinitionService
5479
+ * DEPRECATED - Use `registerSchema` instead.
5480
+ *
5481
+ * Allows an app to register a custom SchemaService
5009
5482
  * for use when information about a resource's schema needs
5010
5483
  * to be queried.
5011
5484
  *
5012
5485
  * This method can only be called more than once, but only one schema
5013
5486
  * definition service may exist. Therefore if you wish to chain services
5014
5487
  * you must lookup the existing service and close over it with the new
5015
- * service by calling `getSchemaDefinitionService` prior to registration.
5488
+ * service by accessing `store.schema` prior to registration.
5016
5489
  *
5017
5490
  * For Example:
5018
5491
  *
@@ -5045,18 +5518,73 @@ class Store {
5045
5518
  * constructor(...args) {
5046
5519
  * super(...args);
5047
5520
  *
5048
- * const schema = this.getSchemaDefinitionService();
5521
+ * const schema = this.schema;
5049
5522
  * this.registerSchemaDefinitionService(new SchemaDelegator(schema));
5050
5523
  * }
5051
5524
  * }
5052
5525
  * ```
5053
5526
  *
5054
5527
  * @method registerSchemaDefinitionService
5055
- * @param {SchemaDefinitionService} schema
5528
+ * @param {SchemaService} schema
5529
+ * @deprecated
5056
5530
  * @public
5057
5531
  */
5058
5532
  registerSchemaDefinitionService(schema) {
5059
- this._schemaDefinitionService = schema;
5533
+ this._schema = schema;
5534
+ }
5535
+ /**
5536
+ * Allows an app to register a custom SchemaService
5537
+ * for use when information about a resource's schema needs
5538
+ * to be queried.
5539
+ *
5540
+ * This method can only be called more than once, but only one schema
5541
+ * definition service may exist. Therefore if you wish to chain services
5542
+ * you must lookup the existing service and close over it with the new
5543
+ * service by accessing `store.schema` prior to registration.
5544
+ *
5545
+ * For Example:
5546
+ *
5547
+ * ```ts
5548
+ * import Store from '@ember-data/store';
5549
+ *
5550
+ * class SchemaDelegator {
5551
+ * constructor(schema) {
5552
+ * this._schema = schema;
5553
+ * }
5554
+ *
5555
+ * doesTypeExist(type: string): boolean {
5556
+ * if (AbstractSchemas.has(type)) {
5557
+ * return true;
5558
+ * }
5559
+ * return this._schema.doesTypeExist(type);
5560
+ * }
5561
+ *
5562
+ * attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
5563
+ * return this._schema.attributesDefinitionFor(identifier);
5564
+ * }
5565
+ *
5566
+ * relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
5567
+ * const schema = AbstractSchemas.get(identifier.type);
5568
+ * return schema || this._schema.relationshipsDefinitionFor(identifier);
5569
+ * }
5570
+ * }
5571
+ *
5572
+ * export default class extends Store {
5573
+ * constructor(...args) {
5574
+ * super(...args);
5575
+ *
5576
+ * const schema = this.schema;
5577
+ * this.registerSchema(new SchemaDelegator(schema));
5578
+ * }
5579
+ * }
5580
+ * ```
5581
+ *
5582
+ * @method registerSchema
5583
+ * @param {SchemaService} schema
5584
+ * @public
5585
+ */
5586
+ registerSchema(schema) {
5587
+ this._schema = schema;
5060
5588
  }
5061
5589
 
5062
5590
  /**
@@ -5587,6 +6115,9 @@ class Store {
5587
6115
  data: {
5588
6116
  record: identifier,
5589
6117
  options
6118
+ },
6119
+ cacheOptions: {
6120
+ [SkipCache]: true
5590
6121
  }
5591
6122
  });
5592
6123
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
@@ -5801,6 +6332,9 @@ class Store {
5801
6332
  type: normalizeModelName$1(modelName),
5802
6333
  query,
5803
6334
  options: options || {}
6335
+ },
6336
+ cacheOptions: {
6337
+ [SkipCache]: true
5804
6338
  }
5805
6339
  });
5806
6340
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
@@ -5903,6 +6437,9 @@ class Store {
5903
6437
  type: normalizeModelName$1(modelName),
5904
6438
  query,
5905
6439
  options: options || {}
6440
+ },
6441
+ cacheOptions: {
6442
+ [SkipCache]: true
5906
6443
  }
5907
6444
  });
5908
6445
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
@@ -6073,6 +6610,9 @@ class Store {
6073
6610
  data: {
6074
6611
  type: normalizeModelName$1(modelName),
6075
6612
  options: options || {}
6613
+ },
6614
+ cacheOptions: {
6615
+ [SkipCache]: true
6076
6616
  }
6077
6617
  });
6078
6618
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
@@ -6461,6 +7001,9 @@ class Store {
6461
7001
  data: {
6462
7002
  options,
6463
7003
  record: identifier
7004
+ },
7005
+ cacheOptions: {
7006
+ [SkipCache]: true
6464
7007
  }
6465
7008
  }).then(document => document.content);
6466
7009
  }
@@ -6800,120 +7343,6 @@ function secretInit(record, cache, identifier, store) {
6800
7343
  StoreMap.set(record, store);
6801
7344
  setCacheFor(record, cache);
6802
7345
  }
6803
- function getHydratedContent(store, request, document) {
6804
- if (Array.isArray(document.data)) {
6805
- const {
6806
- lid
6807
- } = document;
6808
- const {
6809
- recordArrayManager
6810
- } = store;
6811
- if (!lid) {
6812
- return recordArrayManager.createArray({
6813
- identifiers: document.data,
6814
- doc: document,
6815
- query: request
6816
- });
6817
- }
6818
- let managed = recordArrayManager._keyedArrays.get(lid);
6819
- if (!managed) {
6820
- managed = recordArrayManager.createArray({
6821
- identifiers: document.data,
6822
- doc: document
6823
- });
6824
- recordArrayManager._keyedArrays.set(lid, managed);
6825
- } else {
6826
- recordArrayManager.populateManagedArray(managed, document.data, document);
6827
- }
6828
- return managed;
6829
- } else {
6830
- return Object.assign({}, document, {
6831
- data: document.data ? store.peekRecord(document.data) : null
6832
- });
6833
- }
6834
- }
6835
- function calcShouldFetch(store, request, hasCachedValue, lid) {
6836
- const {
6837
- cacheOptions,
6838
- url,
6839
- method
6840
- } = request;
6841
- return cacheOptions?.reload || !hasCachedValue || (store.lifetimes && lid && url && method ? store.lifetimes.isHardExpired(lid, url, method) : false);
6842
- }
6843
- function calcShouldBackgroundFetch(store, request, willFetch, lid) {
6844
- const {
6845
- cacheOptions,
6846
- url,
6847
- method
6848
- } = request;
6849
- return !willFetch && (cacheOptions?.backgroundReload || (store.lifetimes && lid && url && method ? store.lifetimes.isSoftExpired(lid, url, method) : false));
6850
- }
6851
- function fetchContentAndHydrate(next, context, shouldFetch, shouldBackgroundFetch) {
6852
- const {
6853
- store
6854
- } = context.request;
6855
- const shouldHydrate = context.request[Symbol.for('ember-data:enable-hydration')] || false;
6856
- return next(context.request).then(document => {
6857
- store._enableAsyncFlush = true;
6858
- let response;
6859
- store._join(() => {
6860
- response = store.cache.put(document);
6861
- if (shouldFetch && shouldHydrate) {
6862
- response = getHydratedContent(store, context.request, response);
6863
- }
6864
- });
6865
- store._enableAsyncFlush = null;
6866
- if (shouldFetch) {
6867
- return response;
6868
- }
6869
- }, error => {
6870
- store._enableAsyncFlush = true;
6871
- store._join(() => {
6872
- store.cache.put(error);
6873
- });
6874
- store._enableAsyncFlush = null;
6875
-
6876
- // TODO @runspired this is probably not the right thing to throw so make sure we add a test
6877
- if (!shouldBackgroundFetch) {
6878
- throw error;
6879
- }
6880
- });
6881
- }
6882
- const CacheHandler = {
6883
- request(context, next) {
6884
- // if we have no cache or no cache-key skip cache handling
6885
- if (!context.request.store || !(context.request.cacheOptions?.key || context.request.url)) {
6886
- return next(context.request);
6887
- }
6888
- const {
6889
- store
6890
- } = context.request;
6891
- const {
6892
- cacheOptions,
6893
- url,
6894
- method
6895
- } = context.request;
6896
- const lid = cacheOptions?.key || method === 'GET' && url ? url : null;
6897
- const peeked = lid ? store.cache.peekRequest({
6898
- lid
6899
- }) : null;
6900
-
6901
- // determine if we should skip cache
6902
- if (calcShouldFetch(store, context.request, !!peeked, lid)) {
6903
- return fetchContentAndHydrate(next, context, true, false);
6904
- }
6905
-
6906
- // if we have not skipped cache, determine if we should update behind the scenes
6907
- if (calcShouldBackgroundFetch(store, context.request, false, lid)) {
6908
- void fetchContentAndHydrate(next, context, false, true);
6909
- }
6910
- if ('error' in peeked) {
6911
- throw peeked.error;
6912
- }
6913
- const shouldHydrate = context.request[Symbol.for('ember-data:enable-hydration')] || false;
6914
- return Promise.resolve(shouldHydrate ? getHydratedContent(store, context.request, peeked.content) : peeked.content);
6915
- }
6916
- };
6917
7346
  function normalizeModelName(modelName) {
6918
7347
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_HELPERS)) {
6919
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, {