@ember-data/model 4.8.0-alpha.5 → 4.8.0-alpha.6

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.
@@ -0,0 +1,54 @@
1
+ import { deprecate } from '@ember/debug';
2
+
3
+ import { resolve } from 'rsvp';
4
+
5
+ import { PromiseObject } from './promise-proxy-base';
6
+
7
+ function promiseObject<T>(promise: Promise<T>): PromiseObject<T> {
8
+ return PromiseObject.create({
9
+ promise: resolve(promise),
10
+ }) as PromiseObject<T>;
11
+ }
12
+
13
+ // constructor is accessed in some internals but not including it in the copyright for the deprecation
14
+ const ALLOWABLE_METHODS = ['constructor', 'then', 'catch', 'finally'];
15
+ const PROXIED_OBJECT_PROPS = ['content', 'isPending', 'isSettled', 'isRejected', 'isFulfilled', 'promise', 'reason'];
16
+
17
+ export function deprecatedPromiseObject<T>(promise: Promise<T>): PromiseObject<T> {
18
+ const promiseObjectProxy: PromiseObject<T> = promiseObject(promise);
19
+ const handler = {
20
+ get(target: object, prop: string, receiver?: object): unknown {
21
+ if (typeof prop === 'symbol') {
22
+ return Reflect.get(target, prop, receiver);
23
+ }
24
+ if (!ALLOWABLE_METHODS.includes(prop)) {
25
+ deprecate(
26
+ `Accessing ${prop} is deprecated. The return type is being changed fomr PromiseObjectProxy to a Promise. The only available methods to access on this promise are .then, .catch and .finally`,
27
+ false,
28
+ {
29
+ id: 'ember-data:model-save-promise',
30
+ until: '5.0',
31
+ for: '@ember-data/store',
32
+ since: {
33
+ available: '4.4',
34
+ enabled: '4.4',
35
+ },
36
+ }
37
+ );
38
+ }
39
+
40
+ const value: unknown = target[prop];
41
+ if (value && typeof value === 'function' && typeof value.bind === 'function') {
42
+ return value.bind(target);
43
+ }
44
+
45
+ if (PROXIED_OBJECT_PROPS.includes(prop)) {
46
+ return value;
47
+ }
48
+
49
+ return undefined;
50
+ },
51
+ };
52
+
53
+ return new Proxy(promiseObjectProxy, handler);
54
+ }
@@ -260,8 +260,10 @@ function hasMany(type, options) {
260
260
  }
261
261
  }
262
262
  const support = lookupLegacySupport(this);
263
+ const manyArray = support.getManyArray(key);
264
+ assert(`You must pass an array of records to set a hasMany relationship`, Array.isArray(records));
263
265
  this.store._join(() => {
264
- support.setDirtyHasMany(key, records);
266
+ manyArray.splice(0, manyArray.length, ...records);
265
267
  });
266
268
 
267
269
  return support.getHasMany(key);
@@ -1,23 +1,21 @@
1
- import { assert } from '@ember/debug';
1
+ import { assert, deprecate } from '@ember/debug';
2
2
  import { DEBUG } from '@glimmer/env';
3
3
 
4
4
  import { importSync } from '@embroider/macros';
5
5
  import { all, resolve } from 'rsvp';
6
6
 
7
7
  import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
8
+ import { DEPRECATE_PROMISE_PROXIES } from '@ember-data/private-build-infra/deprecations';
8
9
  import type { UpgradedMeta } from '@ember-data/record-data/-private/graph/-edge-definition';
10
+ import type { LocalRelationshipOperation } from '@ember-data/record-data/-private/graph/-operations';
9
11
  import type { ImplicitRelationship } from '@ember-data/record-data/-private/graph/index';
10
12
  import type BelongsToRelationship from '@ember-data/record-data/-private/relationships/state/belongs-to';
11
13
  import type ManyRelationship from '@ember-data/record-data/-private/relationships/state/has-many';
12
14
  import type Store from '@ember-data/store';
13
- import { recordIdentifierFor, storeFor } from '@ember-data/store/-private';
14
- import { IdentifierCache } from '@ember-data/store/-private/caches/identifier-cache';
15
+ import { fastPush, isStableIdentifier, recordIdentifierFor, SOURCE, storeFor } from '@ember-data/store/-private';
16
+ import type { NonSingletonRecordDataManager } from '@ember-data/store/-private/managers/record-data-manager';
15
17
  import type { DSModel } from '@ember-data/types/q/ds-model';
16
- import {
17
- CollectionResourceRelationship,
18
- ResourceIdentifierObject,
19
- SingleResourceRelationship,
20
- } from '@ember-data/types/q/ember-data-json-api';
18
+ import { CollectionResourceRelationship, SingleResourceRelationship } from '@ember-data/types/q/ember-data-json-api';
21
19
  import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
22
20
  import type { RecordData } from '@ember-data/types/q/record-data';
23
21
  import type { JsonApiRelationship } from '@ember-data/types/q/record-data-json-api';
@@ -27,8 +25,7 @@ import type { Dict } from '@ember-data/types/q/utils';
27
25
 
28
26
  import { _findBelongsTo, _findHasMany } from './legacy-data-fetch';
29
27
  import { assertIdentifierHasId } from './legacy-data-utils';
30
- import type { ManyArrayCreateArgs } from './many-array';
31
- import ManyArray from './many-array';
28
+ import RelatedCollection from './many-array';
32
29
  import type { BelongsToProxyCreateArgs, BelongsToProxyMeta } from './promise-belongs-to';
33
30
  import PromiseBelongsTo from './promise-belongs-to';
34
31
  import type { HasManyProxyCreateArgs } from './promise-many-array';
@@ -36,7 +33,6 @@ import PromiseManyArray from './promise-many-array';
36
33
  import BelongsToReference from './references/belongs-to';
37
34
  import HasManyReference from './references/has-many';
38
35
 
39
- type ManyArrayFactory = { create(args: ManyArrayCreateArgs): ManyArray };
40
36
  type PromiseBelongsToFactory = { create(args: BelongsToProxyCreateArgs): PromiseBelongsTo };
41
37
 
42
38
  export class LegacySupport {
@@ -45,8 +41,8 @@ export class LegacySupport {
45
41
  declare recordData: RecordData;
46
42
  declare references: Dict<BelongsToReference | HasManyReference>;
47
43
  declare identifier: StableRecordIdentifier;
48
- declare _manyArrayCache: Dict<ManyArray>;
49
- declare _relationshipPromisesCache: Dict<Promise<ManyArray | RecordInstance>>;
44
+ declare _manyArrayCache: Dict<RelatedCollection>;
45
+ declare _relationshipPromisesCache: Dict<Promise<RelatedCollection | RecordInstance>>;
50
46
  declare _relationshipProxyCache: Dict<PromiseManyArray | PromiseBelongsTo>;
51
47
 
52
48
  declare isDestroying: boolean;
@@ -58,12 +54,38 @@ export class LegacySupport {
58
54
  this.identifier = recordIdentifierFor(record);
59
55
  this.recordData = this.store._instanceCache.getRecordData(this.identifier);
60
56
 
61
- this._manyArrayCache = Object.create(null) as Dict<ManyArray>;
62
- this._relationshipPromisesCache = Object.create(null) as Dict<Promise<ManyArray | RecordInstance>>;
57
+ this._manyArrayCache = Object.create(null) as Dict<RelatedCollection>;
58
+ this._relationshipPromisesCache = Object.create(null) as Dict<Promise<RelatedCollection | RecordInstance>>;
63
59
  this._relationshipProxyCache = Object.create(null) as Dict<PromiseManyArray | PromiseBelongsTo>;
64
60
  this.references = Object.create(null) as Dict<BelongsToReference>;
65
61
  }
66
62
 
63
+ _syncArray(array: RelatedCollection) {
64
+ // It’s possible the parent side of the relationship may have been destroyed by this point
65
+ if (this.isDestroyed || this.isDestroying) {
66
+ return;
67
+ }
68
+ const currentState = array[SOURCE];
69
+ const identifier = this.identifier;
70
+
71
+ let [identifiers, jsonApi] = this._getCurrentState(identifier, array.key);
72
+
73
+ if (jsonApi.meta) {
74
+ array.meta = jsonApi.meta;
75
+ }
76
+
77
+ if (jsonApi.links) {
78
+ array.links = jsonApi.links;
79
+ }
80
+
81
+ currentState.length = 0;
82
+ fastPush(currentState, identifiers);
83
+ }
84
+
85
+ updateCache(operation: LocalRelationshipOperation): void {
86
+ this.recordData.update(operation);
87
+ }
88
+
67
89
  _findBelongsTo(
68
90
  key: string,
69
91
  resource: SingleResourceRelationship,
@@ -104,8 +126,8 @@ export class LegacySupport {
104
126
  getBelongsTo(key: string, options?: FindOptions): PromiseBelongsTo | RecordInstance | null {
105
127
  const { identifier, recordData } = this;
106
128
  let resource = recordData.getRelationship(this.identifier, key) as SingleResourceRelationship;
107
- let relatedIdentifier =
108
- resource && resource.data ? this.store.identifierCache.getOrCreateRecordIdentifier(resource.data) : null;
129
+ let relatedIdentifier = resource && resource.data ? resource.data : null;
130
+ assert(`Expected a stable identifier`, !relatedIdentifier || isStableIdentifier(relatedIdentifier));
109
131
 
110
132
  const store = this.store;
111
133
  const graphFor = (
@@ -151,12 +173,45 @@ export class LegacySupport {
151
173
  }
152
174
 
153
175
  setDirtyBelongsTo(key: string, value: RecordInstance | null) {
154
- return this.recordData.setBelongsTo(this.identifier, key, extractIdentifierFromRecord(value));
176
+ return this.recordData.update(
177
+ {
178
+ op: 'replaceRelatedRecord',
179
+ record: this.identifier,
180
+ field: key,
181
+ value: extractIdentifierFromRecord(value),
182
+ },
183
+ // @ts-expect-error
184
+ true
185
+ );
155
186
  }
156
187
 
157
- getManyArray(key: string, definition?: UpgradedMeta): ManyArray {
188
+ _getCurrentState(
189
+ identifier: StableRecordIdentifier,
190
+ field: string
191
+ ): [StableRecordIdentifier[], CollectionResourceRelationship] {
192
+ let jsonApi = (this.recordData as NonSingletonRecordDataManager).getRelationship(
193
+ identifier,
194
+ field,
195
+ true
196
+ ) as CollectionResourceRelationship;
197
+ const cache = this.store._instanceCache;
198
+ let identifiers: StableRecordIdentifier[] = [];
199
+ if (jsonApi.data) {
200
+ for (let i = 0; i < jsonApi.data.length; i++) {
201
+ const identifier = jsonApi.data[i];
202
+ assert(`Expected a stable identifier`, isStableIdentifier(identifier));
203
+ if (cache.recordIsLoaded(identifier, true)) {
204
+ identifiers.push(identifier);
205
+ }
206
+ }
207
+ }
208
+
209
+ return [identifiers, jsonApi];
210
+ }
211
+
212
+ getManyArray(key: string, definition?: UpgradedMeta): RelatedCollection {
158
213
  assert('hasMany only works with the @ember-data/record-data package', HAS_RECORD_DATA_PACKAGE);
159
- let manyArray: ManyArray | undefined = this._manyArrayCache[key];
214
+ let manyArray: RelatedCollection | undefined = this._manyArrayCache[key];
160
215
  if (!definition) {
161
216
  const graphFor = (
162
217
  importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
@@ -165,17 +220,23 @@ export class LegacySupport {
165
220
  }
166
221
 
167
222
  if (!manyArray) {
168
- manyArray = (ManyArray as unknown as ManyArrayFactory).create({
223
+ const [identifiers, doc] = this._getCurrentState(this.identifier, key);
224
+
225
+ manyArray = new RelatedCollection({
169
226
  store: this.store,
170
- type: this.store.modelFor(definition.type),
227
+ type: definition.type,
171
228
  identifier: this.identifier,
172
229
  recordData: this.recordData,
230
+ identifiers,
173
231
  key,
232
+ meta: doc.meta || null,
233
+ links: doc.links || null,
174
234
  isPolymorphic: definition.isPolymorphic,
175
235
  isAsync: definition.isAsync,
176
236
  _inverseIsAsync: definition.inverseIsAsync,
177
- legacySupport: this,
237
+ manager: this,
178
238
  isLoaded: !definition.isAsync,
239
+ allowMutation: true,
179
240
  });
180
241
  this._manyArrayCache[key] = manyArray;
181
242
  }
@@ -186,18 +247,24 @@ export class LegacySupport {
186
247
  fetchAsyncHasMany(
187
248
  key: string,
188
249
  relationship: ManyRelationship,
189
- manyArray: ManyArray,
250
+ manyArray: RelatedCollection,
190
251
  options?: FindOptions
191
- ): Promise<ManyArray> {
252
+ ): Promise<RelatedCollection> {
192
253
  if (HAS_RECORD_DATA_PACKAGE) {
193
- let loadingPromise = this._relationshipPromisesCache[key] as Promise<ManyArray> | undefined;
254
+ let loadingPromise = this._relationshipPromisesCache[key] as Promise<RelatedCollection> | undefined;
194
255
  if (loadingPromise) {
195
256
  return loadingPromise;
196
257
  }
197
258
 
198
259
  const jsonApi = this.recordData.getRelationship(this.identifier, key) as CollectionResourceRelationship;
260
+ const promise = this._findHasManyByJsonApiResource(jsonApi, this.identifier, relationship, options);
199
261
 
200
- loadingPromise = this._findHasManyByJsonApiResource(jsonApi, this.identifier, relationship, options).then(
262
+ if (!promise) {
263
+ manyArray.isLoaded = true;
264
+ return resolve(manyArray);
265
+ }
266
+
267
+ loadingPromise = promise.then(
201
268
  () => handleCompletedRelationshipRequest(this, key, relationship, manyArray),
202
269
  (e: Error) => handleCompletedRelationshipRequest(this, key, relationship, manyArray, e)
203
270
  );
@@ -233,7 +300,7 @@ export class LegacySupport {
233
300
  assert(`hasMany only works with the @ember-data/record-data package`);
234
301
  }
235
302
 
236
- getHasMany(key: string, options?: FindOptions): PromiseManyArray | ManyArray {
303
+ getHasMany(key: string, options?: FindOptions): PromiseManyArray | RelatedCollection {
237
304
  if (HAS_RECORD_DATA_PACKAGE) {
238
305
  const graphFor = (
239
306
  importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
@@ -264,11 +331,6 @@ export class LegacySupport {
264
331
  assert(`hasMany only works with the @ember-data/record-data package`);
265
332
  }
266
333
 
267
- setDirtyHasMany(key: string, records: RecordInstance[]) {
268
- assertRecordsPassedToHasMany(records);
269
- return this.recordData.setHasMany(this.identifier, key, extractIdentifiersFromRecords(records));
270
- }
271
-
272
334
  _updatePromiseProxyFor(kind: 'hasMany', key: string, args: HasManyProxyCreateArgs): PromiseManyArray;
273
335
  _updatePromiseProxyFor(kind: 'belongsTo', key: string, args: BelongsToProxyCreateArgs): PromiseBelongsTo;
274
336
  _updatePromiseProxyFor(
@@ -358,10 +420,10 @@ export class LegacySupport {
358
420
  parentIdentifier: StableRecordIdentifier,
359
421
  relationship: ManyRelationship,
360
422
  options: FindOptions = {}
361
- ): Promise<void | unknown[]> {
423
+ ): Promise<void | unknown[]> | void {
362
424
  if (HAS_RECORD_DATA_PACKAGE) {
363
425
  if (!resource) {
364
- return resolve();
426
+ return;
365
427
  }
366
428
  const { definition, state } = relationship;
367
429
  const adapter = this.store.adapterFor(definition.type);
@@ -411,11 +473,19 @@ export class LegacySupport {
411
473
 
412
474
  // fetch using data, pulling from local cache if possible
413
475
  if (!shouldForceReload && !isStale && (preferLocalCache || hasLocalPartialData)) {
476
+ if (allInverseRecordsAreLoaded) {
477
+ return;
478
+ }
414
479
  assert(`Expected collection to be an array`, Array.isArray(resource.data));
480
+ if (allInverseRecordsAreLoaded) {
481
+ return;
482
+ }
415
483
  let finds = new Array(resource.data.length);
484
+ let cache = this.store._instanceCache;
416
485
  for (let i = 0; i < resource.data.length; i++) {
417
- let identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resource.data[i]);
418
- finds[i] = this.store._instanceCache._fetchDataIfNeededForIdentifier(identifier, options);
486
+ const identifier = resource.data[i];
487
+ assert(`expected a stable identifier`, isStableIdentifier(identifier));
488
+ finds[i] = cache._fetchDataIfNeededForIdentifier(identifier, options);
419
489
  }
420
490
 
421
491
  return all(finds);
@@ -425,8 +495,9 @@ export class LegacySupport {
425
495
 
426
496
  // fetch by data
427
497
  if (hasData || hasLocalPartialData) {
428
- assert(`Expected collection to be an array`, Array.isArray(resource.data));
429
- let identifiers = resource.data.map((json) => this.store.identifierCache.getOrCreateRecordIdentifier(json));
498
+ const identifiers = resource.data;
499
+ assert(`Expected collection to be an array`, Array.isArray(identifiers));
500
+ assert(`Expected stable identifiers`, identifiers.every(isStableIdentifier));
430
501
  let fetches = new Array(identifiers.length);
431
502
  const manager = this.store._fetchManager;
432
503
 
@@ -441,7 +512,7 @@ export class LegacySupport {
441
512
 
442
513
  // we were explicitly told we have no data and no links.
443
514
  // TODO if the relationshipIsStale, should we hit the adapter anyway?
444
- return resolve();
515
+ return;
445
516
  }
446
517
  assert(`hasMany only works with the @ember-data/record-data package`);
447
518
  }
@@ -456,7 +527,8 @@ export class LegacySupport {
456
527
  return resolve(null);
457
528
  }
458
529
 
459
- const identifier = resource.data ? this.store.identifierCache.getOrCreateRecordIdentifier(resource.data) : null;
530
+ const identifier = resource.data ? resource.data : null;
531
+ assert(`Expected a stable identifier`, !identifier || isStableIdentifier(identifier));
460
532
 
461
533
  let { isStale, hasDematerializedInverse, hasReceivedData, isEmpty, shouldForceReload } = relationship.state;
462
534
 
@@ -557,8 +629,8 @@ function handleCompletedRelationshipRequest(
557
629
  recordExt: LegacySupport,
558
630
  key: string,
559
631
  relationship: ManyRelationship,
560
- value: ManyArray
561
- ): ManyArray;
632
+ value: RelatedCollection
633
+ ): RelatedCollection;
562
634
  function handleCompletedRelationshipRequest(
563
635
  recordExt: LegacySupport,
564
636
  key: string,
@@ -570,16 +642,16 @@ function handleCompletedRelationshipRequest(
570
642
  recordExt: LegacySupport,
571
643
  key: string,
572
644
  relationship: ManyRelationship,
573
- value: ManyArray,
645
+ value: RelatedCollection,
574
646
  error: Error
575
647
  ): never;
576
648
  function handleCompletedRelationshipRequest(
577
649
  recordExt: LegacySupport,
578
650
  key: string,
579
651
  relationship: BelongsToRelationship | ManyRelationship,
580
- value: ManyArray | StableRecordIdentifier | null,
652
+ value: RelatedCollection | StableRecordIdentifier | null,
581
653
  error?: Error
582
- ): ManyArray | RecordInstance | null {
654
+ ): RelatedCollection | RecordInstance | null {
583
655
  delete recordExt._relationshipPromisesCache[key];
584
656
  relationship.state.shouldForceReload = false;
585
657
  const isHasMany = relationship.definition.kind === 'hasMany';
@@ -587,7 +659,7 @@ function handleCompletedRelationshipRequest(
587
659
  if (isHasMany) {
588
660
  // we don't notify the record property here to avoid refetch
589
661
  // only the many array
590
- (value as ManyArray).notify();
662
+ (value as RelatedCollection).notify();
591
663
  }
592
664
 
593
665
  if (error) {
@@ -611,7 +683,7 @@ function handleCompletedRelationshipRequest(
611
683
  }
612
684
 
613
685
  if (isHasMany) {
614
- (value as ManyArray).set('isLoaded', true);
686
+ (value as RelatedCollection).isLoaded = true;
615
687
  }
616
688
 
617
689
  relationship.state.hasFailedLoadAttempt = false;
@@ -619,33 +691,10 @@ function handleCompletedRelationshipRequest(
619
691
  relationship.state.isStale = false;
620
692
 
621
693
  return isHasMany || !value
622
- ? (value as ManyArray | null)
694
+ ? (value as RelatedCollection | null)
623
695
  : recordExt.store.peekRecord(value as StableRecordIdentifier);
624
696
  }
625
697
 
626
- function assertRecordsPassedToHasMany(records: RecordInstance[]) {
627
- assert(`You must pass an array of records to set a hasMany relationship`, Array.isArray(records));
628
- assert(
629
- `All elements of a hasMany relationship must be instances of Model, you passed ${records
630
- .map((r) => `${typeof r}`)
631
- .join(', ')}`,
632
- (function () {
633
- return records.every((record) => {
634
- try {
635
- recordIdentifierFor(record);
636
- return true;
637
- } catch {
638
- return false;
639
- }
640
- });
641
- })()
642
- );
643
- }
644
-
645
- function extractIdentifiersFromRecords(records: RecordInstance[]): StableRecordIdentifier[] {
646
- return records.map(extractIdentifierFromRecord) as StableRecordIdentifier[];
647
- }
648
-
649
698
  type PromiseProxyRecord = { then(): void; content: RecordInstance | null | undefined };
650
699
 
651
700
  function extractIdentifierFromRecord(recordOrPromiseRecord: PromiseProxyRecord | RecordInstance | null) {
@@ -653,12 +702,25 @@ function extractIdentifierFromRecord(recordOrPromiseRecord: PromiseProxyRecord |
653
702
  return null;
654
703
  }
655
704
 
656
- if (isPromiseRecord(recordOrPromiseRecord)) {
705
+ if (DEPRECATE_PROMISE_PROXIES && isPromiseRecord(recordOrPromiseRecord)) {
657
706
  let content = recordOrPromiseRecord.content;
658
707
  assert(
659
708
  '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.',
660
709
  content !== undefined
661
710
  );
711
+ deprecate(
712
+ `You passed in a PromiseProxy to a Relationship API that now expects a resolved value. await the value before setting it.`,
713
+ false,
714
+ {
715
+ id: 'ember-data:deprecate-promise-proxies',
716
+ until: '5.0',
717
+ since: {
718
+ enabled: '4.8',
719
+ available: '4.8',
720
+ },
721
+ for: 'ember-data',
722
+ }
723
+ );
662
724
  return content ? recordIdentifierFor(content) : null;
663
725
  }
664
726
 
@@ -681,30 +743,21 @@ function anyUnloaded(store: Store, relationship: ManyRelationship) {
681
743
  }
682
744
 
683
745
  function areAllInverseRecordsLoaded(store: Store, resource: JsonApiRelationship): boolean {
684
- const cache = store.identifierCache;
746
+ const instanceCache = store._instanceCache;
747
+ const identifiers = resource.data;
685
748
 
686
- if (Array.isArray(resource.data)) {
749
+ if (Array.isArray(identifiers)) {
750
+ assert(`Expected stable identifiers`, identifiers.every(isStableIdentifier));
687
751
  // treat as collection
688
752
  // check for unloaded records
689
- let hasEmptyRecords = resource.data.reduce((hasEmptyModel, resourceIdentifier) => {
690
- return hasEmptyModel || isEmpty(store, cache, resourceIdentifier);
691
- }, false);
692
-
693
- return !hasEmptyRecords;
694
- } else {
695
- // treat as single resource
696
- if (!resource.data) {
697
- return true;
698
- } else {
699
- return !isEmpty(store, cache, resource.data);
700
- }
753
+ return identifiers.every((identifier: StableRecordIdentifier) => instanceCache.recordIsLoaded(identifier));
701
754
  }
702
- }
703
755
 
704
- function isEmpty(store: Store, cache: IdentifierCache, resource: ResourceIdentifierObject): boolean {
705
- const identifier = cache.getOrCreateRecordIdentifier(resource);
706
- const recordData = store._instanceCache.__instances.recordData.get(identifier);
707
- return !recordData || recordData.isEmpty(identifier);
756
+ // treat as single resource
757
+ if (!identifiers) return true;
758
+
759
+ assert(`Expected stable identifiers`, isStableIdentifier(identifiers));
760
+ return instanceCache.recordIsLoaded(identifiers);
708
761
  }
709
762
 
710
763
  function isBelongsTo(