@ember-data/model 4.12.0-alpha.2 → 4.12.0-alpha.20

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,8 +1,8 @@
1
- import { macroCondition, isDevelopingApp, getOwnConfig, importSync, dependencySatisfies } from '@embroider/macros';
1
+ import { macroCondition, getOwnConfig, importSync } from '@embroider/macros';
2
2
  import { assert, deprecate, warn, inspect } from '@ember/debug';
3
3
  import EmberObject, { computed, get } from '@ember/object';
4
- import { recordIdentifierFor, storeFor } from '@ember-data/store';
5
- import { recordDataFor, RecordArray, MUTATE, SOURCE, recordIdentifierFor as recordIdentifierFor$1, IDENTIFIER_ARRAY_TAG, notifyArray, isStableIdentifier, storeFor as storeFor$1, fastPush, coerceId } from '@ember-data/store/-private';
4
+ import { recordIdentifierFor, storeFor as storeFor$1 } from '@ember-data/store';
5
+ import { peekCache, RecordArray, MUTATE, SOURCE, recordIdentifierFor as recordIdentifierFor$1, IDENTIFIER_ARRAY_TAG, notifyArray, isStableIdentifier, storeFor, fastPush, coerceId } from '@ember-data/store/-private';
6
6
  import { dasherize } from '@ember/string';
7
7
  import ArrayMixin, { A, NativeArray } from '@ember/array';
8
8
  import { singularize } from 'ember-inflector';
@@ -10,7 +10,6 @@ import { dependentKeyCompat } from '@ember/object/compat';
10
10
  import { run } from '@ember/runloop';
11
11
  import { cached, tracked } from '@glimmer/tracking';
12
12
  import Ember from 'ember';
13
- import { resolve, all } from 'rsvp';
14
13
  import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
15
14
  import ObjectProxy from '@ember/object/proxy';
16
15
  import ArrayProxy from '@ember/array/proxy';
@@ -103,9 +102,7 @@ function computedMacroWithOptionalParams(fn) {
103
102
  ```
104
103
 
105
104
  ```app/transforms/text.js
106
- import Transform from '@ember-data/serializer/transform';
107
-
108
- export default class TextTransform extends Transform {
105
+ export default class TextTransform {
109
106
  serialize(value, options) {
110
107
  if (options.uppercase) {
111
108
  return value.toUpperCase();
@@ -117,6 +114,10 @@ function computedMacroWithOptionalParams(fn) {
117
114
  deserialize(value) {
118
115
  return value;
119
116
  }
117
+
118
+ static create() {
119
+ return new this();
120
+ }
120
121
  }
121
122
  ```
122
123
 
@@ -142,7 +143,7 @@ function attr(type, options) {
142
143
  };
143
144
  return computed({
144
145
  get(key) {
145
- if (macroCondition(isDevelopingApp())) {
146
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
146
147
  if (['currentState'].indexOf(key) !== -1) {
147
148
  throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your attr on ${this.constructor.toString()}`);
148
149
  }
@@ -150,20 +151,20 @@ function attr(type, options) {
150
151
  if (this.isDestroyed || this.isDestroying) {
151
152
  return;
152
153
  }
153
- return recordDataFor(this).getAttr(recordIdentifierFor(this), key);
154
+ return peekCache(this).getAttr(recordIdentifierFor(this), key);
154
155
  },
155
156
  set(key, value) {
156
- if (macroCondition(isDevelopingApp())) {
157
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
157
158
  if (['currentState'].indexOf(key) !== -1) {
158
159
  throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your attr on ${this.constructor.toString()}`);
159
160
  }
160
161
  }
161
162
  assert(`Attempted to set '${key}' on the deleted record ${recordIdentifierFor(this)}`, !this.currentState.isDeleted);
162
163
  const identifier = recordIdentifierFor(this);
163
- const recordData = storeFor(this)._instanceCache.getRecordData(identifier);
164
- let currentValue = recordData.getAttr(identifier, key);
164
+ const cache = peekCache(this);
165
+ let currentValue = cache.getAttr(identifier, key);
165
166
  if (currentValue !== value) {
166
- recordData.setAttr(identifier, key, value);
167
+ cache.setAttr(identifier, key, value);
167
168
  if (!this.isValid) {
168
169
  const {
169
170
  errors
@@ -214,7 +215,7 @@ function _applyDecoratedDescriptor(target, property, decorators, descriptor, con
214
215
  const PromiseObject = ObjectProxy.extend(PromiseProxyMixin);
215
216
  function promiseObject(promise) {
216
217
  return PromiseObject.create({
217
- promise: resolve(promise)
218
+ promise
218
219
  });
219
220
  }
220
221
 
@@ -225,7 +226,7 @@ const PROXIED_OBJECT_PROPS = ['content', 'isPending', 'isSettled', 'isRejected',
225
226
  const ProxySymbolString = String(Symbol.for('PROXY_CONTENT'));
226
227
  function deprecatedPromiseObject(promise) {
227
228
  const promiseObjectProxy = promiseObject(promise);
228
- if (macroCondition(!isDevelopingApp())) {
229
+ if (macroCondition(!getOwnConfig().env.DEBUG)) {
229
230
  return promiseObjectProxy;
230
231
  }
231
232
  const handler = {
@@ -268,6 +269,11 @@ function deprecatedPromiseObject(promise) {
268
269
  return new Proxy(promiseObjectProxy, handler);
269
270
  }
270
271
  var _dec$1, _dec2, _dec3, _dec4, _class$6, _descriptor$5, _descriptor2$2;
272
+
273
+ /**
274
+ @module @ember-data/model
275
+ */
276
+
271
277
  // we force the type here to our own construct because mixin and extend patterns
272
278
  // lose generic signatures. We also do this because we need to Omit `clear` from
273
279
  // the type of ArrayProxy as we override it's signature.
@@ -632,384 +638,6 @@ let Errors = (_dec$1 = computed(), _dec2 = mapBy('content', 'message'), _dec3 =
632
638
  writable: true,
633
639
  initializer: null
634
640
  })), _class$6));
635
- function iterateData(data, fn) {
636
- if (Array.isArray(data)) {
637
- return data.map(fn);
638
- } else {
639
- return fn(data);
640
- }
641
- }
642
- function assertIdentifierHasId(identifier) {
643
- assert(`Attempted to schedule a fetch for a record without an id.`, identifier.id !== null);
644
- }
645
- function normalizeResponseHelper(serializer, store, modelClass, payload, id, requestType) {
646
- let normalizedResponse = serializer ? serializer.normalizeResponse(store, modelClass, payload, id, requestType) : payload;
647
- validateDocumentStructure(normalizedResponse);
648
- return normalizedResponse;
649
- }
650
- function validateDocumentStructure(doc) {
651
- if (macroCondition(isDevelopingApp())) {
652
- let errors = [];
653
- if (!doc || typeof doc !== 'object') {
654
- errors.push('Top level of a JSON API document must be an object');
655
- } else {
656
- if (!('data' in doc) && !('errors' in doc) && !('meta' in doc)) {
657
- errors.push('One or more of the following keys must be present: "data", "errors", "meta".');
658
- } else {
659
- if ('data' in doc && 'errors' in doc) {
660
- errors.push('Top level keys "errors" and "data" cannot both be present in a JSON API document');
661
- }
662
- }
663
- if ('data' in doc) {
664
- if (!(doc.data === null || Array.isArray(doc.data) || typeof doc.data === 'object')) {
665
- errors.push('data must be null, an object, or an array');
666
- }
667
- }
668
- if ('meta' in doc) {
669
- if (typeof doc.meta !== 'object') {
670
- errors.push('meta must be an object');
671
- }
672
- }
673
- if ('errors' in doc) {
674
- if (!Array.isArray(doc.errors)) {
675
- errors.push('errors must be an array');
676
- }
677
- }
678
- if ('links' in doc) {
679
- if (typeof doc.links !== 'object') {
680
- errors.push('links must be an object');
681
- }
682
- }
683
- if ('jsonapi' in doc) {
684
- if (typeof doc.jsonapi !== 'object') {
685
- errors.push('jsonapi must be an object');
686
- }
687
- }
688
- if ('included' in doc) {
689
- if (typeof doc.included !== 'object') {
690
- errors.push('included must be an array');
691
- }
692
- }
693
- }
694
- assert(`Response must be normalized to a valid JSON API document:\n\t* ${errors.join('\n\t* ')}`, errors.length === 0);
695
- }
696
- }
697
- function _findHasMany(adapter, store, identifier, link, relationship, options) {
698
- const record = store._instanceCache.getRecord(identifier);
699
- const snapshot = store._instanceCache.createSnapshot(identifier, options);
700
- let modelClass = store.modelFor(relationship.type);
701
- let useLink = !link || typeof link === 'string';
702
- let relatedLink = useLink ? link : link.href;
703
- let promise = adapter.findHasMany(store, snapshot, relatedLink, relationship);
704
- let label = `DS: Handle Adapter#findHasMany of '${identifier.type}' : '${relationship.type}'`;
705
- promise = guardDestroyedStore(promise, store, label);
706
- promise = promise.then(adapterPayload => {
707
- if (!_objectIsAlive(record)) {
708
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
709
- deprecate(`A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`, false, {
710
- id: 'ember-data:rsvp-unresolved-async',
711
- until: '5.0',
712
- for: '@ember-data/store',
713
- since: {
714
- available: '4.5',
715
- enabled: '4.5'
716
- }
717
- });
718
- }
719
- }
720
- assert(`You made a 'findHasMany' request for a ${identifier.type}'s '${relationship.key}' relationship, using link '${link}' , but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload));
721
- let serializer = store.serializerFor(relationship.type);
722
- let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findHasMany');
723
- assert(`fetched the hasMany relationship '${relationship.name}' for ${identifier.type}:${identifier.id} with link '${link}', but no data member is present in the response. If no data exists, the response should set { data: [] }`, 'data' in payload && Array.isArray(payload.data));
724
- payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
725
- return store._push(payload);
726
- }, null, `DS: Extract payload of '${identifier.type}' : hasMany '${relationship.type}'`);
727
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
728
- promise = _guard(promise, _bind(_objectIsAlive, record));
729
- }
730
- return promise;
731
- }
732
- function _findBelongsTo(store, identifier, link, relationship, options) {
733
- const record = store._instanceCache.getRecord(identifier);
734
- let adapter = store.adapterFor(identifier.type);
735
- assert(`You tried to load a belongsTo relationship but you have no adapter (for ${identifier.type})`, adapter);
736
- assert(`You tried to load a belongsTo relationship from a specified 'link' in the original payload but your adapter does not implement 'findBelongsTo'`, typeof adapter.findBelongsTo === 'function');
737
- let snapshot = store._instanceCache.createSnapshot(identifier, options);
738
- let modelClass = store.modelFor(relationship.type);
739
- let useLink = !link || typeof link === 'string';
740
- let relatedLink = useLink ? link : link.href;
741
- let promise = adapter.findBelongsTo(store, snapshot, relatedLink, relationship);
742
- let label = `DS: Handle Adapter#findBelongsTo of ${identifier.type} : ${relationship.type}`;
743
- promise = guardDestroyedStore(promise, store, label);
744
- promise = _guard(promise, _bind(_objectIsAlive, record));
745
- promise = promise.then(adapterPayload => {
746
- if (!_objectIsAlive(record)) {
747
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
748
- deprecate(`A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`, false, {
749
- id: 'ember-data:rsvp-unresolved-async',
750
- until: '5.0',
751
- for: '@ember-data/store',
752
- since: {
753
- available: '4.5',
754
- enabled: '4.5'
755
- }
756
- });
757
- }
758
- }
759
- let serializer = store.serializerFor(relationship.type);
760
- let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo');
761
- assert(`fetched the belongsTo relationship '${relationship.name}' for ${identifier.type}:${identifier.id} with link '${link}', but no data member is present in the response. If no data exists, the response should set { data: null }`, 'data' in payload && (payload.data === null || typeof payload.data === 'object' && !Array.isArray(payload.data)));
762
- if (!payload.data && !payload.links && !payload.meta) {
763
- return null;
764
- }
765
- payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
766
- return store._push(payload);
767
- }, null, `DS: Extract payload of ${identifier.type} : ${relationship.type}`);
768
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
769
- promise = _guard(promise, _bind(_objectIsAlive, record));
770
- }
771
- return promise;
772
- }
773
-
774
- // sync
775
- // iterate over records in payload.data
776
- // for each record
777
- // assert that record.relationships[inverse] is either undefined (so we can fix it)
778
- // or provide a data: {id, type} that matches the record that requested it
779
- // return the relationship data for the parent
780
- function syncRelationshipDataFromLink(store, payload, parentIdentifier, relationship) {
781
- // ensure the right hand side (incoming payload) points to the parent record that
782
- // requested this relationship
783
- let relationshipData = payload.data ? iterateData(payload.data, (data, index) => {
784
- const {
785
- id,
786
- type
787
- } = data;
788
- ensureRelationshipIsSetToParent(data, parentIdentifier, store, relationship, index);
789
- return {
790
- id,
791
- type
792
- };
793
- }) : null;
794
- const relatedDataHash = {};
795
- if ('meta' in payload) {
796
- relatedDataHash.meta = payload.meta;
797
- }
798
- if ('links' in payload) {
799
- relatedDataHash.links = payload.links;
800
- }
801
- if ('data' in payload) {
802
- relatedDataHash.data = relationshipData;
803
- }
804
-
805
- // now, push the left hand side (the parent record) to ensure things are in sync, since
806
- // the payload will be pushed with store._push
807
- const parentPayload = {
808
- id: parentIdentifier.id,
809
- type: parentIdentifier.type,
810
- relationships: {
811
- [relationship.key]: relatedDataHash
812
- }
813
- };
814
- if (!Array.isArray(payload.included)) {
815
- payload.included = [];
816
- }
817
- payload.included.push(parentPayload);
818
- return payload;
819
- }
820
- function ensureRelationshipIsSetToParent(payload, parentIdentifier, store, parentRelationship, index) {
821
- let {
822
- id,
823
- type
824
- } = payload;
825
- if (!payload.relationships) {
826
- payload.relationships = {};
827
- }
828
- let {
829
- relationships
830
- } = payload;
831
- let inverse = getInverse(store, parentIdentifier, parentRelationship, type);
832
- if (inverse) {
833
- let {
834
- inverseKey,
835
- kind
836
- } = inverse;
837
- let relationshipData = relationships[inverseKey] && relationships[inverseKey].data;
838
- if (macroCondition(isDevelopingApp())) {
839
- if (typeof relationshipData !== 'undefined' && !relationshipDataPointsToParent(relationshipData, parentIdentifier)) {
840
- let inspect = function inspect(thing) {
841
- return `'${JSON.stringify(thing)}'`;
842
- };
843
- let quotedType = inspect(type);
844
- let quotedInverse = inspect(inverseKey);
845
- let expected = inspect({
846
- id: parentIdentifier.id,
847
- type: parentIdentifier.type
848
- });
849
- let expectedModel = `${parentIdentifier.type}:${parentIdentifier.id}`;
850
- let got = inspect(relationshipData);
851
- let prefix = typeof index === 'number' ? `data[${index}]` : `data`;
852
- let path = `${prefix}.relationships.${inverseKey}.data`;
853
- let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null;
854
- let relationshipFetched = `${expectedModel}.${parentRelationship.kind}("${parentRelationship.name}")`;
855
- let includedRecord = `<${type}:${id}>`;
856
- let message = [`Encountered mismatched relationship: Ember Data expected ${path} in the payload from ${relationshipFetched} to include ${expected} but got ${got} instead.\n`, `The ${includedRecord} record loaded at ${prefix} in the payload specified ${other} as its ${quotedInverse}, but should have specified ${expectedModel} (the record the relationship is being loaded from) as its ${quotedInverse} instead.`, `This could mean that the response for ${relationshipFetched} may have accidentally returned ${quotedType} records that aren't related to ${expectedModel} and could be related to a different ${parentIdentifier.type} record instead.`, `Ember Data has corrected the ${includedRecord} record's ${quotedInverse} relationship to ${expectedModel} so that ${relationshipFetched} will include ${includedRecord}.`, `Please update the response from the server or change your serializer to either ensure that the response for only includes ${quotedType} records that specify ${expectedModel} as their ${quotedInverse}, or omit the ${quotedInverse} relationship from the response.`].join('\n');
857
- assert(message);
858
- }
859
- }
860
- if (kind !== 'hasMany' || typeof relationshipData !== 'undefined') {
861
- relationships[inverseKey] = relationships[inverseKey] || {};
862
- relationships[inverseKey].data = fixRelationshipData(relationshipData, kind, parentIdentifier);
863
- }
864
- }
865
- }
866
- function metaIsRelationshipDefinition(meta) {
867
- return typeof meta._inverseKey === 'function';
868
- }
869
- function inverseForRelationship(store, identifier, key) {
870
- const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor(identifier)[key];
871
- if (!definition) {
872
- return null;
873
- }
874
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE)) {
875
- if (metaIsRelationshipDefinition(definition)) {
876
- const modelClass = store.modelFor(identifier.type);
877
- return definition._inverseKey(store, modelClass);
878
- }
879
- }
880
- assert(`Expected the relationship defintion to specify the inverse type or null.`, definition.options?.inverse === null || typeof definition.options?.inverse === 'string' && definition.options.inverse.length > 0);
881
- return definition.options.inverse;
882
- }
883
- function getInverse(store, parentIdentifier, parentRelationship, type) {
884
- let {
885
- name: lhs_relationshipName
886
- } = parentRelationship;
887
- let {
888
- type: parentType
889
- } = parentIdentifier;
890
- let inverseKey = inverseForRelationship(store, {
891
- type: parentType
892
- }, lhs_relationshipName);
893
- if (inverseKey) {
894
- const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor({
895
- type
896
- });
897
- let {
898
- kind
899
- } = definition[inverseKey];
900
- return {
901
- inverseKey,
902
- kind
903
- };
904
- }
905
- }
906
- function relationshipDataPointsToParent(relationshipData, identifier) {
907
- if (relationshipData === null) {
908
- return false;
909
- }
910
- if (Array.isArray(relationshipData)) {
911
- if (relationshipData.length === 0) {
912
- return false;
913
- }
914
- for (let i = 0; i < relationshipData.length; i++) {
915
- let entry = relationshipData[i];
916
- if (validateRelationshipEntry(entry, identifier)) {
917
- return true;
918
- }
919
- }
920
- } else {
921
- return validateRelationshipEntry(relationshipData, identifier);
922
- }
923
- return false;
924
- }
925
- function fixRelationshipData(relationshipData, relationshipKind, {
926
- id,
927
- type
928
- }) {
929
- let parentRelationshipData = {
930
- id,
931
- type
932
- };
933
- let payload;
934
- if (relationshipKind === 'hasMany') {
935
- payload = relationshipData || [];
936
- if (relationshipData) {
937
- // these arrays could be massive so this is better than filter
938
- // Note: this is potentially problematic if type/id are not in the
939
- // same state of normalization.
940
- let found = relationshipData.find(v => {
941
- return v.type === parentRelationshipData.type && v.id === parentRelationshipData.id;
942
- });
943
- if (!found) {
944
- payload.push(parentRelationshipData);
945
- }
946
- } else {
947
- payload.push(parentRelationshipData);
948
- }
949
- } else {
950
- payload = relationshipData || {};
951
- Object.assign(payload, parentRelationshipData);
952
- }
953
- return payload;
954
- }
955
- function validateRelationshipEntry({
956
- id
957
- }, {
958
- id: parentModelID
959
- }) {
960
- return id && id.toString() === parentModelID;
961
- }
962
- function _bind(fn, ...args) {
963
- return function () {
964
- return fn.apply(undefined, args);
965
- };
966
- }
967
- function _guard(promise, test) {
968
- let guarded = promise.finally(() => {
969
- if (!test()) {
970
- guarded._subscribers.length = 0;
971
- }
972
- });
973
- return guarded;
974
- }
975
- function _objectIsAlive(object) {
976
- return !(object.isDestroyed || object.isDestroying);
977
- }
978
- function payloadIsNotBlank(adapterPayload) {
979
- if (Array.isArray(adapterPayload)) {
980
- return true;
981
- } else {
982
- return Object.keys(adapterPayload || {}).length;
983
- }
984
- }
985
- function guardDestroyedStore(promise, store, label) {
986
- let token;
987
- if (macroCondition(isDevelopingApp())) {
988
- token = store._trackAsyncRequestStart(label);
989
- }
990
- let wrapperPromise = resolve(promise, label).then(_v => {
991
- if (!_objectIsAlive(store)) {
992
- if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
993
- deprecate(`A Promise did not resolve by the time the store was destroyed. This will error in a future release.`, false, {
994
- id: 'ember-data:rsvp-unresolved-async',
995
- until: '5.0',
996
- for: '@ember-data/store',
997
- since: {
998
- available: '4.5',
999
- enabled: '4.5'
1000
- }
1001
- });
1002
- }
1003
- }
1004
- return promise;
1005
- });
1006
- return _guard(wrapperPromise, () => {
1007
- if (macroCondition(isDevelopingApp())) {
1008
- store._trackAsyncRequestEnd(token);
1009
- }
1010
- return _objectIsAlive(store);
1011
- });
1012
- }
1013
641
 
1014
642
  /**
1015
643
  A `ManyArray` is a `MutableArray` that represents the contents of a has-many
@@ -1118,7 +746,7 @@ class RelatedCollection extends RecordArray {
1118
746
  switch (prop) {
1119
747
  case 'length 0':
1120
748
  {
1121
- this._manager.updateCache({
749
+ this._manager.mutate({
1122
750
  op: 'replaceRelatedRecords',
1123
751
  record: this.identifier,
1124
752
  field: this.key,
@@ -1129,7 +757,7 @@ class RelatedCollection extends RecordArray {
1129
757
  case 'replace cell':
1130
758
  {
1131
759
  const [index, prior, value] = args;
1132
- this._manager.updateCache({
760
+ this._manager.mutate({
1133
761
  op: 'replaceRelatedRecord',
1134
762
  record: this.identifier,
1135
763
  field: this.key,
@@ -1140,7 +768,7 @@ class RelatedCollection extends RecordArray {
1140
768
  break;
1141
769
  }
1142
770
  case 'push':
1143
- this._manager.updateCache({
771
+ this._manager.mutate({
1144
772
  op: 'addToRelatedRecords',
1145
773
  record: this.identifier,
1146
774
  field: this.key,
@@ -1149,7 +777,7 @@ class RelatedCollection extends RecordArray {
1149
777
  break;
1150
778
  case 'pop':
1151
779
  if (result) {
1152
- this._manager.updateCache({
780
+ this._manager.mutate({
1153
781
  op: 'removeFromRelatedRecords',
1154
782
  record: this.identifier,
1155
783
  field: this.key,
@@ -1158,7 +786,7 @@ class RelatedCollection extends RecordArray {
1158
786
  }
1159
787
  break;
1160
788
  case 'unshift':
1161
- this._manager.updateCache({
789
+ this._manager.mutate({
1162
790
  op: 'addToRelatedRecords',
1163
791
  record: this.identifier,
1164
792
  field: this.key,
@@ -1168,7 +796,7 @@ class RelatedCollection extends RecordArray {
1168
796
  break;
1169
797
  case 'shift':
1170
798
  if (result) {
1171
- this._manager.updateCache({
799
+ this._manager.mutate({
1172
800
  op: 'removeFromRelatedRecords',
1173
801
  record: this.identifier,
1174
802
  field: this.key,
@@ -1178,7 +806,7 @@ class RelatedCollection extends RecordArray {
1178
806
  }
1179
807
  break;
1180
808
  case 'sort':
1181
- this._manager.updateCache({
809
+ this._manager.mutate({
1182
810
  op: 'sortRelatedRecords',
1183
811
  record: this.identifier,
1184
812
  field: this.key,
@@ -1190,7 +818,7 @@ class RelatedCollection extends RecordArray {
1190
818
  const [start, removeCount, ...adds] = args;
1191
819
  // detect a full replace
1192
820
  if (removeCount > 0 && adds.length === this[SOURCE].length) {
1193
- this._manager.updateCache({
821
+ this._manager.mutate({
1194
822
  op: 'replaceRelatedRecords',
1195
823
  record: this.identifier,
1196
824
  field: this.key,
@@ -1199,7 +827,7 @@ class RelatedCollection extends RecordArray {
1199
827
  return;
1200
828
  }
1201
829
  if (removeCount > 0) {
1202
- this._manager.updateCache({
830
+ this._manager.mutate({
1203
831
  op: 'removeFromRelatedRecords',
1204
832
  record: this.identifier,
1205
833
  field: this.key,
@@ -1208,7 +836,7 @@ class RelatedCollection extends RecordArray {
1208
836
  });
1209
837
  }
1210
838
  if (adds?.length) {
1211
- this._manager.updateCache({
839
+ this._manager.mutate({
1212
840
  op: 'addToRelatedRecords',
1213
841
  record: this.identifier,
1214
842
  field: this.key,
@@ -1278,6 +906,7 @@ class RelatedCollection extends RecordArray {
1278
906
  const {
1279
907
  store
1280
908
  } = this;
909
+ assert(`Expected modelName to be set`, this.modelName);
1281
910
  const record = store.createRecord(this.modelName, hash);
1282
911
  this.push(record);
1283
912
  return record;
@@ -1286,7 +915,7 @@ class RelatedCollection extends RecordArray {
1286
915
  RelatedCollection.prototype.isAsync = false;
1287
916
  RelatedCollection.prototype.isPolymorphic = false;
1288
917
  RelatedCollection.prototype.identifier = null;
1289
- RelatedCollection.prototype.recordData = null;
918
+ RelatedCollection.prototype.cache = null;
1290
919
  RelatedCollection.prototype._inverseIsAsync = false;
1291
920
  RelatedCollection.prototype.key = '';
1292
921
  RelatedCollection.prototype.DEPRECATED_CLASS_NAME = 'ManyArray';
@@ -1328,6 +957,9 @@ function isPromiseRecord$1(record) {
1328
957
  return !!record.then;
1329
958
  }
1330
959
  var _dec, _class$5;
960
+
961
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
962
+
1331
963
  const Extended = PromiseObject;
1332
964
 
1333
965
  /**
@@ -1374,6 +1006,26 @@ let PromiseBelongsTo = (_dec = computed(), (_class$5 = class PromiseBelongsTo ex
1374
1006
  }
1375
1007
  }, (_applyDecoratedDescriptor(_class$5.prototype, "id", [cached], Object.getOwnPropertyDescriptor(_class$5.prototype, "id"), _class$5.prototype), _applyDecoratedDescriptor(_class$5.prototype, "meta", [_dec], Object.getOwnPropertyDescriptor(_class$5.prototype, "meta"), _class$5.prototype)), _class$5));
1376
1008
  var _class$4, _descriptor$4, _descriptor2$1, _descriptor3, _descriptor4, _descriptor5;
1009
+
1010
+ /**
1011
+ @module @ember-data/model
1012
+ */
1013
+ /**
1014
+ This class is returned as the result of accessing an async hasMany relationship
1015
+ on an instance of a Model extending from `@ember-data/model`.
1016
+
1017
+ A PromiseManyArray is an iterable proxy that allows templates to consume related
1018
+ ManyArrays and update once their contents are no longer pending.
1019
+
1020
+ In your JS code you should resolve the promise first.
1021
+
1022
+ ```js
1023
+ const comments = await post.comments;
1024
+ ```
1025
+
1026
+ @class PromiseManyArray
1027
+ @public
1028
+ */
1377
1029
  let PromiseManyArray = (_class$4 = class PromiseManyArray {
1378
1030
  // @deprecated (isDestroyed is not deprecated)
1379
1031
 
@@ -1430,7 +1082,7 @@ let PromiseManyArray = (_class$4 = class PromiseManyArray {
1430
1082
  }
1431
1083
  return false;
1432
1084
  };
1433
- } else if (macroCondition(isDevelopingApp())) {
1085
+ } else if (macroCondition(getOwnConfig().env.DEBUG)) {
1434
1086
  const meta = Ember.meta(this);
1435
1087
  meta.hasMixin = mixin => {
1436
1088
  assert(`Do not use A() on an EmberData PromiseManyArray`);
@@ -1652,7 +1304,7 @@ function tapPromise(proxy, promise) {
1652
1304
  proxy.isSettled = false;
1653
1305
  proxy.isFulfilled = false;
1654
1306
  proxy.isRejected = false;
1655
- return resolve(promise).then(content => {
1307
+ return Promise.resolve(promise).then(content => {
1656
1308
  proxy.isPending = false;
1657
1309
  proxy.isFulfilled = true;
1658
1310
  proxy.isSettled = true;
@@ -1715,7 +1367,7 @@ if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_MANY_ARRAY_BEHA
1715
1367
  `record.relationshipFor(key)`.
1716
1368
  */
1717
1369
  let assertPolymorphicType;
1718
- if (macroCondition(isDevelopingApp())) {
1370
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
1719
1371
  let checkPolymorphic = function checkPolymorphic(modelClass, addedModelClass) {
1720
1372
  if (modelClass.__isMixin) {
1721
1373
  return modelClass.__mixin.detect(addedModelClass.PrototypeMixin) ||
@@ -1967,7 +1619,8 @@ let BelongsToReference = (_class$3 = class BelongsToReference {
1967
1619
  }
1968
1620
  _resource() {
1969
1621
  this._ref; // subscribe
1970
- return this.store._instanceCache.getRecordData(this.___identifier).getRelationship(this.___identifier, this.key);
1622
+ const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this.store._instanceCache.getResourceCache(this.___identifier) : this.store.cache;
1623
+ return cache.getRelationship(this.___identifier, this.key);
1971
1624
  }
1972
1625
 
1973
1626
  /**
@@ -2057,7 +1710,7 @@ let BelongsToReference = (_class$3 = class BelongsToReference {
2057
1710
  let jsonApiDoc = data;
2058
1711
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
2059
1712
  if (data.then) {
2060
- jsonApiDoc = await resolve(data);
1713
+ jsonApiDoc = await data;
2061
1714
  if (jsonApiDoc !== data) {
2062
1715
  deprecate(`You passed in a Promise to a Reference API that now expects a resolved value. await the value before setting it.`, false, {
2063
1716
  id: 'ember-data:deprecate-promise-proxies',
@@ -2072,7 +1725,7 @@ let BelongsToReference = (_class$3 = class BelongsToReference {
2072
1725
  }
2073
1726
  }
2074
1727
  let record = this.store.push(jsonApiDoc);
2075
- if (macroCondition(isDevelopingApp())) {
1728
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
2076
1729
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
2077
1730
  assertPolymorphicType(this.belongsToRelationship.identifier, this.belongsToRelationship.definition, recordIdentifierFor$1(record), this.store);
2078
1731
  }
@@ -2332,7 +1985,8 @@ let HasManyReference = (_class$2 = class HasManyReference {
2332
1985
  return [];
2333
1986
  }
2334
1987
  _resource() {
2335
- return this.store._instanceCache.getRecordData(this.___identifier).getRelationship(this.___identifier, this.key);
1988
+ const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this.store._instanceCache.getResourceCache(this.___identifier) : this.store.cache;
1989
+ return cache.getRelationship(this.___identifier, this.key);
2336
1990
  }
2337
1991
 
2338
1992
  /**
@@ -2549,7 +2203,7 @@ let HasManyReference = (_class$2 = class HasManyReference {
2549
2203
  let payload = objectOrPromise;
2550
2204
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_PROMISE_PROXIES)) {
2551
2205
  if (objectOrPromise.then) {
2552
- payload = await resolve(objectOrPromise);
2206
+ payload = await objectOrPromise;
2553
2207
  if (payload !== objectOrPromise) {
2554
2208
  deprecate(`You passed in a Promise to a Reference API that now expects a resolved value. await the value before setting it.`, false, {
2555
2209
  id: 'ember-data:deprecate-promise-proxies',
@@ -2582,7 +2236,7 @@ let HasManyReference = (_class$2 = class HasManyReference {
2582
2236
  data: obj
2583
2237
  });
2584
2238
  }
2585
- if (macroCondition(isDevelopingApp())) {
2239
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
2586
2240
  let relationshipMeta = this.hasManyRelationship.definition;
2587
2241
  let identifier = this.hasManyRelationship.identifier;
2588
2242
 
@@ -2775,9 +2429,9 @@ let HasManyReference = (_class$2 = class HasManyReference {
2775
2429
  class LegacySupport {
2776
2430
  constructor(record) {
2777
2431
  this.record = record;
2778
- this.store = storeFor$1(record);
2432
+ this.store = storeFor(record);
2779
2433
  this.identifier = recordIdentifierFor$1(record);
2780
- this.recordData = this.store._instanceCache.getRecordData(this.identifier);
2434
+ this.cache = peekCache(record);
2781
2435
  this._manyArrayCache = Object.create(null);
2782
2436
  this._relationshipPromisesCache = Object.create(null);
2783
2437
  this._relationshipProxyCache = Object.create(null);
@@ -2800,8 +2454,8 @@ class LegacySupport {
2800
2454
  currentState.length = 0;
2801
2455
  fastPush(currentState, identifiers);
2802
2456
  }
2803
- updateCache(operation) {
2804
- this.recordData.update(operation);
2457
+ mutate(mutation) {
2458
+ this.cache.mutate(mutation);
2805
2459
  }
2806
2460
  _findBelongsTo(key, resource, relationship, options) {
2807
2461
  // TODO @runspired follow up if parent isNew then we should not be attempting load here
@@ -2816,7 +2470,7 @@ class LegacySupport {
2816
2470
  const graphFor = importSync('@ember-data/graph/-private').graphFor;
2817
2471
  const relationship = graphFor(this.store).get(this.identifier, key);
2818
2472
  assert(`Expected ${key} to be a belongs-to relationship`, isBelongsTo(relationship));
2819
- let resource = this.recordData.getRelationship(this.identifier, key);
2473
+ let resource = this.cache.getRelationship(this.identifier, key);
2820
2474
  relationship.state.hasFailedLoadAttempt = false;
2821
2475
  relationship.state.shouldForceReload = true;
2822
2476
  let promise = this._findBelongsTo(key, resource, relationship, options);
@@ -2830,9 +2484,9 @@ class LegacySupport {
2830
2484
  getBelongsTo(key, options) {
2831
2485
  const {
2832
2486
  identifier,
2833
- recordData
2487
+ cache
2834
2488
  } = this;
2835
- let resource = recordData.getRelationship(this.identifier, key);
2489
+ let resource = cache.getRelationship(this.identifier, key);
2836
2490
  let relatedIdentifier = resource && resource.data ? resource.data : null;
2837
2491
  assert(`Expected a stable identifier`, !relatedIdentifier || isStableIdentifier(relatedIdentifier));
2838
2492
  const store = this.store;
@@ -2868,7 +2522,7 @@ class LegacySupport {
2868
2522
  }
2869
2523
  }
2870
2524
  setDirtyBelongsTo(key, value) {
2871
- return this.recordData.update({
2525
+ return this.cache.mutate({
2872
2526
  op: 'replaceRelatedRecord',
2873
2527
  record: this.identifier,
2874
2528
  field: key,
@@ -2878,7 +2532,7 @@ class LegacySupport {
2878
2532
  true);
2879
2533
  }
2880
2534
  _getCurrentState(identifier, field) {
2881
- let jsonApi = this.recordData.getRelationship(identifier, field, true);
2535
+ let jsonApi = this.cache.getRelationship(identifier, field, true);
2882
2536
  const cache = this.store._instanceCache;
2883
2537
  let identifiers = [];
2884
2538
  if (jsonApi.data) {
@@ -2893,7 +2547,7 @@ class LegacySupport {
2893
2547
  return [identifiers, jsonApi];
2894
2548
  }
2895
2549
  getManyArray(key, definition) {
2896
- if (macroCondition(dependencySatisfies("@ember-data/json-api", "*"))) {
2550
+ if (macroCondition(getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
2897
2551
  let manyArray = this._manyArrayCache[key];
2898
2552
  if (!definition) {
2899
2553
  const graphFor = importSync('@ember-data/graph/-private').graphFor;
@@ -2905,7 +2559,7 @@ class LegacySupport {
2905
2559
  store: this.store,
2906
2560
  type: definition.type,
2907
2561
  identifier: this.identifier,
2908
- recordData: this.recordData,
2562
+ cache: this.cache,
2909
2563
  identifiers,
2910
2564
  key,
2911
2565
  meta: doc.meta || null,
@@ -2924,16 +2578,16 @@ class LegacySupport {
2924
2578
  assert('hasMany only works with the @ember-data/json-api package');
2925
2579
  }
2926
2580
  fetchAsyncHasMany(key, relationship, manyArray, options) {
2927
- if (macroCondition(dependencySatisfies("@ember-data/json-api", "*"))) {
2581
+ if (macroCondition(getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
2928
2582
  let loadingPromise = this._relationshipPromisesCache[key];
2929
2583
  if (loadingPromise) {
2930
2584
  return loadingPromise;
2931
2585
  }
2932
- const jsonApi = this.recordData.getRelationship(this.identifier, key);
2586
+ const jsonApi = this.cache.getRelationship(this.identifier, key);
2933
2587
  const promise = this._findHasManyByJsonApiResource(jsonApi, this.identifier, relationship, options);
2934
2588
  if (!promise) {
2935
2589
  manyArray.isLoaded = true;
2936
- return resolve(manyArray);
2590
+ return Promise.resolve(manyArray);
2937
2591
  }
2938
2592
  loadingPromise = promise.then(() => handleCompletedRelationshipRequest(this, key, relationship, manyArray), e => handleCompletedRelationshipRequest(this, key, relationship, manyArray, e));
2939
2593
  this._relationshipPromisesCache[key] = loadingPromise;
@@ -2942,7 +2596,7 @@ class LegacySupport {
2942
2596
  assert('hasMany only works with the @ember-data/json-api package');
2943
2597
  }
2944
2598
  reloadHasMany(key, options) {
2945
- if (macroCondition(dependencySatisfies("@ember-data/json-api", "*"))) {
2599
+ if (macroCondition(getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
2946
2600
  let loadingPromise = this._relationshipPromisesCache[key];
2947
2601
  if (loadingPromise) {
2948
2602
  return loadingPromise;
@@ -2967,7 +2621,7 @@ class LegacySupport {
2967
2621
  assert(`hasMany only works with the @ember-data/json-api package`);
2968
2622
  }
2969
2623
  getHasMany(key, options) {
2970
- if (macroCondition(dependencySatisfies("@ember-data/json-api", "*"))) {
2624
+ if (macroCondition(getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
2971
2625
  const graphFor = importSync('@ember-data/graph/-private').graphFor;
2972
2626
  const relationship = graphFor(this.store).get(this.identifier, key);
2973
2627
  const {
@@ -3025,7 +2679,7 @@ class LegacySupport {
3025
2679
  referenceFor(kind, name) {
3026
2680
  let reference = this.references[name];
3027
2681
  if (!reference) {
3028
- if (macroCondition(!dependencySatisfies("@ember-data/json-api", "*"))) {
2682
+ if (macroCondition(!getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
3029
2683
  // TODO @runspired while this feels odd, it is not a regression in capability because we do
3030
2684
  // not today support references pulling from RecordDatas other than our own
3031
2685
  // because of the intimate API access involved. This is something we will need to redesign.
@@ -3034,7 +2688,7 @@ class LegacySupport {
3034
2688
  const graphFor = importSync('@ember-data/graph/-private').graphFor;
3035
2689
  const graph = graphFor(this.store);
3036
2690
  const relationship = graph.get(this.identifier, name);
3037
- if (macroCondition(isDevelopingApp())) {
2691
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
3038
2692
  if (kind) {
3039
2693
  let modelName = this.identifier.type;
3040
2694
  let actualRelationshipKind = relationship.definition.kind;
@@ -3052,7 +2706,7 @@ class LegacySupport {
3052
2706
  return reference;
3053
2707
  }
3054
2708
  _findHasManyByJsonApiResource(resource, parentIdentifier, relationship, options = {}) {
3055
- if (macroCondition(dependencySatisfies("@ember-data/json-api", "*"))) {
2709
+ if (macroCondition(getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
3056
2710
  if (!resource) {
3057
2711
  return;
3058
2712
  }
@@ -3069,66 +2723,52 @@ class LegacySupport {
3069
2723
  shouldForceReload
3070
2724
  } = state;
3071
2725
  const allInverseRecordsAreLoaded = areAllInverseRecordsLoaded(this.store, resource);
3072
- const shouldFindViaLink = resource.links && resource.links.related && (typeof adapter.findHasMany === 'function' || typeof resource.data === 'undefined') && (shouldForceReload || hasDematerializedInverse || isStale || !allInverseRecordsAreLoaded && !isEmpty);
2726
+ const identifiers = resource.data;
2727
+ const shouldFindViaLink = resource.links && resource.links.related && (typeof adapter.findHasMany === 'function' || typeof identifiers === 'undefined') && (shouldForceReload || hasDematerializedInverse || isStale || !allInverseRecordsAreLoaded && !isEmpty);
2728
+ const relationshipMeta = this.store.getSchemaDefinitionService().relationshipsDefinitionFor({
2729
+ type: definition.inverseType
2730
+ })[definition.key];
2731
+ const request = {
2732
+ useLink: shouldFindViaLink,
2733
+ field: relationshipMeta,
2734
+ links: resource.links,
2735
+ meta: resource.meta,
2736
+ options,
2737
+ record: parentIdentifier
2738
+ };
3073
2739
 
3074
2740
  // fetch via link
3075
2741
  if (shouldFindViaLink) {
3076
- // findHasMany, although not public, does not need to care about our upgrade relationship definitions
3077
- // and can stick with the public definition API for now.
3078
- const relationshipMeta = this.store.getSchemaDefinitionService().relationshipsDefinitionFor({
3079
- type: definition.inverseType
3080
- })[definition.key];
3081
- let adapter = this.store.adapterFor(parentIdentifier.type);
3082
-
3083
- /*
3084
- If a relationship was originally populated by the adapter as a link
3085
- (as opposed to a list of IDs), this method is called when the
3086
- relationship is fetched.
3087
- The link (which is usually a URL) is passed through unchanged, so the
3088
- adapter can make whatever request it wants.
3089
- The usual use-case is for the server to register a URL as a link, and
3090
- then use that URL in the future to make a request for the relationship.
3091
- */
3092
- assert(`You tried to load a hasMany relationship but you have no adapter (for ${parentIdentifier.type})`, adapter);
3093
- assert(`You tried to load a hasMany relationship from a specified 'link' in the original payload but your adapter does not implement 'findHasMany'`, typeof adapter.findHasMany === 'function');
3094
- return _findHasMany(adapter, this.store, parentIdentifier, resource.links.related, relationshipMeta, options);
2742
+ assert(`Expected collection to be an array`, !identifiers || Array.isArray(identifiers));
2743
+ assert(`Expected stable identifiers`, !identifiers || identifiers.every(isStableIdentifier));
2744
+ return this.store.request({
2745
+ op: 'findHasMany',
2746
+ records: identifiers || [],
2747
+ data: request,
2748
+ cacheOptions: {
2749
+ [Symbol.for('ember-data:skip-cache')]: true
2750
+ }
2751
+ });
3095
2752
  }
3096
2753
  const preferLocalCache = hasReceivedData && !isEmpty;
3097
- const hasLocalPartialData = hasDematerializedInverse || isEmpty && Array.isArray(resource.data) && resource.data.length > 0;
3098
-
3099
- // fetch using data, pulling from local cache if possible
3100
- if (!shouldForceReload && !isStale && (preferLocalCache || hasLocalPartialData)) {
3101
- if (allInverseRecordsAreLoaded) {
3102
- return;
3103
- }
3104
- assert(`Expected collection to be an array`, Array.isArray(resource.data));
3105
- if (allInverseRecordsAreLoaded) {
3106
- return;
3107
- }
3108
- let finds = new Array(resource.data.length);
3109
- let cache = this.store._instanceCache;
3110
- for (let i = 0; i < resource.data.length; i++) {
3111
- const identifier = resource.data[i];
3112
- assert(`expected a stable identifier`, isStableIdentifier(identifier));
3113
- finds[i] = cache._fetchDataIfNeededForIdentifier(identifier, options);
3114
- }
3115
- return all(finds);
2754
+ const hasLocalPartialData = hasDematerializedInverse || isEmpty && Array.isArray(identifiers) && identifiers.length > 0;
2755
+ const attemptLocalCache = !shouldForceReload && !isStale && (preferLocalCache || hasLocalPartialData);
2756
+ if (attemptLocalCache && allInverseRecordsAreLoaded) {
2757
+ return;
3116
2758
  }
3117
- let hasData = hasReceivedData && !isEmpty;
3118
-
3119
- // fetch by data
3120
- if (hasData || hasLocalPartialData) {
3121
- const identifiers = resource.data;
2759
+ const hasData = hasReceivedData && !isEmpty;
2760
+ if (attemptLocalCache || hasData || hasLocalPartialData) {
3122
2761
  assert(`Expected collection to be an array`, Array.isArray(identifiers));
3123
2762
  assert(`Expected stable identifiers`, identifiers.every(isStableIdentifier));
3124
- let fetches = new Array(identifiers.length);
3125
- const manager = this.store._fetchManager;
3126
- for (let i = 0; i < identifiers.length; i++) {
3127
- let identifier = identifiers[i];
3128
- assertIdentifierHasId(identifier);
3129
- fetches[i] = manager.scheduleFetch(identifier, options);
3130
- }
3131
- return all(fetches);
2763
+ options.reload = options.reload || !attemptLocalCache || undefined;
2764
+ return this.store.request({
2765
+ op: 'findHasMany',
2766
+ records: identifiers,
2767
+ data: request,
2768
+ cacheOptions: {
2769
+ [Symbol.for('ember-data:skip-cache')]: true
2770
+ }
2771
+ });
3132
2772
  }
3133
2773
 
3134
2774
  // we were explicitly told we have no data and no links.
@@ -3139,7 +2779,14 @@ class LegacySupport {
3139
2779
  }
3140
2780
  _findBelongsToByJsonApiResource(resource, parentIdentifier, relationship, options = {}) {
3141
2781
  if (!resource) {
3142
- return resolve(null);
2782
+ return Promise.resolve(null);
2783
+ }
2784
+
2785
+ // interleaved promises mean that we MUST cache this here
2786
+ // in order to prevent infinite re-render if the request
2787
+ // fails.
2788
+ if (this._pending) {
2789
+ return this._pending;
3143
2790
  }
3144
2791
  const identifier = resource.data ? resource.data : null;
3145
2792
  assert(`Expected a stable identifier`, !identifier || isStableIdentifier(identifier));
@@ -3150,53 +2797,71 @@ class LegacySupport {
3150
2797
  isEmpty,
3151
2798
  shouldForceReload
3152
2799
  } = relationship.state;
3153
-
3154
- // short circuit if we are already loading
3155
- let pendingRequest = identifier && this.store._fetchManager.getPendingFetch(identifier, options);
3156
- if (pendingRequest) {
3157
- return pendingRequest;
3158
- }
3159
2800
  const allInverseRecordsAreLoaded = areAllInverseRecordsLoaded(this.store, resource);
3160
2801
  const shouldFindViaLink = resource.links?.related && (shouldForceReload || hasDematerializedInverse || isStale || !allInverseRecordsAreLoaded && !isEmpty);
2802
+ const relationshipMeta = this.store.getSchemaDefinitionService().relationshipsDefinitionFor(this.identifier)[relationship.definition.key];
2803
+ assert(`Attempted to access a belongsTo relationship but no definition exists for it`, relationshipMeta);
2804
+ const request = {
2805
+ useLink: shouldFindViaLink,
2806
+ field: relationshipMeta,
2807
+ links: resource.links,
2808
+ meta: resource.meta,
2809
+ options,
2810
+ record: parentIdentifier
2811
+ };
3161
2812
 
3162
2813
  // fetch via link
3163
2814
  if (shouldFindViaLink) {
3164
- const relationshipMeta = this.store.getSchemaDefinitionService().relationshipsDefinitionFor(this.identifier)[relationship.definition.key];
3165
- assert(`Attempted to access a belongsTo relationship but no definition exists for it`, relationshipMeta);
3166
- return _findBelongsTo(this.store, parentIdentifier, resource.links.related, relationshipMeta, options);
2815
+ const future = this.store.request({
2816
+ op: 'findBelongsTo',
2817
+ records: identifier ? [identifier] : [],
2818
+ data: request,
2819
+ cacheOptions: {
2820
+ [Symbol.for('ember-data:skip-cache')]: true
2821
+ }
2822
+ });
2823
+ this._pending = future.then(doc => doc.content).finally(() => {
2824
+ this._pending = null;
2825
+ });
2826
+ return this._pending;
3167
2827
  }
3168
- let preferLocalCache = hasReceivedData && allInverseRecordsAreLoaded && !isEmpty;
3169
- let hasLocalPartialData = hasDematerializedInverse || isEmpty && resource.data;
2828
+ const preferLocalCache = hasReceivedData && allInverseRecordsAreLoaded && !isEmpty;
2829
+ const hasLocalPartialData = hasDematerializedInverse || isEmpty && resource.data;
3170
2830
  // null is explicit empty, undefined is "we don't know anything"
3171
- const localDataIsEmpty = resource.data === undefined || resource.data === null;
3172
-
3173
- // fetch using data, pulling from local cache if possible
3174
- if (!shouldForceReload && !isStale && (preferLocalCache || hasLocalPartialData)) {
3175
- /*
3176
- We have canonical data, but our local state is empty
3177
- */
3178
- if (localDataIsEmpty) {
3179
- return resolve(null);
3180
- }
3181
- if (!identifier) {
3182
- assert(`No Information found for ${resource.data.lid}`, identifier);
3183
- }
3184
- return this.store._instanceCache._fetchDataIfNeededForIdentifier(identifier, options);
3185
- }
3186
- let resourceIsLocal = !localDataIsEmpty && resource.data.id === null;
3187
- if (identifier && resourceIsLocal) {
3188
- return resolve(identifier);
3189
- }
3190
-
3191
- // fetch by data
3192
- if (identifier && !localDataIsEmpty) {
3193
- assertIdentifierHasId(identifier);
3194
- return this.store._fetchManager.scheduleFetch(identifier, options);
2831
+ const localDataIsEmpty = !identifier;
2832
+ const attemptLocalCache = !shouldForceReload && !isStale && (preferLocalCache || hasLocalPartialData);
2833
+
2834
+ // we dont need to fetch and are empty
2835
+ if (attemptLocalCache && localDataIsEmpty) {
2836
+ return Promise.resolve(null);
2837
+ }
2838
+
2839
+ // we dont need to fetch because we are local state
2840
+ const resourceIsLocal = identifier?.id === null;
2841
+ if (attemptLocalCache && allInverseRecordsAreLoaded || resourceIsLocal) {
2842
+ return Promise.resolve(identifier);
2843
+ }
2844
+
2845
+ // we may need to fetch
2846
+ if (identifier) {
2847
+ assert(`Cannot fetch belongs-to relationship with no information`, identifier);
2848
+ options.reload = options.reload || !attemptLocalCache || undefined;
2849
+ this._pending = this.store.request({
2850
+ op: 'findBelongsTo',
2851
+ records: [identifier],
2852
+ data: request,
2853
+ cacheOptions: {
2854
+ [Symbol.for('ember-data:skip-cache')]: true
2855
+ }
2856
+ }).then(doc => doc.content).finally(() => {
2857
+ this._pending = null;
2858
+ });
2859
+ return this._pending;
3195
2860
  }
3196
2861
 
3197
2862
  // we were explicitly told we have no data and no links.
3198
2863
  // TODO if the relationshipIsStale, should we hit the adapter anyway?
3199
- return resolve(null);
2864
+ return Promise.resolve(null);
3200
2865
  }
3201
2866
  destroy() {
3202
2867
  this.isDestroying = true;
@@ -3245,11 +2910,14 @@ function handleCompletedRelationshipRequest(recordExt, key, relationship, value,
3245
2910
  if (proxy.content && proxy.content.isDestroying) {
3246
2911
  proxy.set('content', null);
3247
2912
  }
2913
+ recordExt.store.notifications._flush();
3248
2914
  }
3249
2915
  throw error;
3250
2916
  }
3251
2917
  if (isHasMany) {
3252
2918
  value.isLoaded = true;
2919
+ } else {
2920
+ recordExt.store.notifications._flush();
3253
2921
  }
3254
2922
  relationship.state.hasFailedLoadAttempt = false;
3255
2923
  // only set to not stale if no error is thrown
@@ -3356,7 +3024,8 @@ function notifyRelationship(identifier, key, record, meta) {
3356
3024
  }
3357
3025
  function notifyAttribute(store, identifier, key, record) {
3358
3026
  let currentValue = cacheFor(record, key);
3359
- if (currentValue !== store._instanceCache.getRecordData(identifier).getAttr(identifier, key)) {
3027
+ const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? peekCache(record) : store.cache;
3028
+ if (currentValue !== cache.getAttr(identifier, key)) {
3360
3029
  record.notifyPropertyChange(key);
3361
3030
  }
3362
3031
  }
@@ -3491,11 +3160,11 @@ root
3491
3160
  let RecordState = (_class3 = class RecordState {
3492
3161
  constructor(record) {
3493
3162
  _initializerDefineProperty(this, "isSaving", _descriptor2, this);
3494
- const store = storeFor(record);
3163
+ const store = storeFor$1(record);
3495
3164
  const identity = recordIdentifierFor$1(record);
3496
3165
  this.identifier = identity;
3497
3166
  this.record = record;
3498
- this.cache = store._instanceCache.getRecordData(identity);
3167
+ this.cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? peekCache(record) : store.cache;
3499
3168
  this.pendingCount = 0;
3500
3169
  this.fulfilledCount = 0;
3501
3170
  this.rejectedCount = 0;
@@ -3555,7 +3224,7 @@ let RecordState = (_class3 = class RecordState {
3555
3224
 
3556
3225
  // we instantiate lazily
3557
3226
  // so we grab anything we don't have yet
3558
- if (macroCondition(!isDevelopingApp())) {
3227
+ if (macroCondition(!getOwnConfig().env.DEBUG)) {
3559
3228
  const lastRequest = requests.getLastRequestForRecord(identity);
3560
3229
  if (lastRequest) {
3561
3230
  handleRequest(lastRequest);
@@ -3580,7 +3249,7 @@ let RecordState = (_class3 = class RecordState {
3580
3249
  });
3581
3250
  }
3582
3251
  destroy() {
3583
- storeFor(this.record).notifications.unsubscribe(this.handler);
3252
+ storeFor$1(this.record).notifications.unsubscribe(this.handler);
3584
3253
  }
3585
3254
  notify(key) {
3586
3255
  getTag(this, key).notify();
@@ -3814,7 +3483,7 @@ class RelationshipDefinition {
3814
3483
  inverse = modelClass.inverseFor(this.key, store);
3815
3484
  }
3816
3485
  // TODO make this error again for the non-polymorphic case
3817
- if (macroCondition(isDevelopingApp())) {
3486
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
3818
3487
  if (!this.options.polymorphic) {
3819
3488
  modelClass.typeForRelationship(this.key, store);
3820
3489
  }
@@ -3839,6 +3508,7 @@ function lookupLegacySupport(record) {
3839
3508
  const identifier = recordIdentifierFor(record);
3840
3509
  let support = LEGACY_SUPPORT.get(identifier);
3841
3510
  if (!support) {
3511
+ assert(`Memory Leak Detected`, !record.isDestroyed && !record.isDestroying);
3842
3512
  support = new LegacySupport(record);
3843
3513
  LEGACY_SUPPORT.set(identifier, support);
3844
3514
  LEGACY_SUPPORT.set(record, support);
@@ -3897,7 +3567,7 @@ function computeOnce(target, key, desc) {
3897
3567
  }
3898
3568
 
3899
3569
  /**
3900
- Base class from which Models can be define.
3570
+ Base class from which Models can be defined.
3901
3571
 
3902
3572
  ```js
3903
3573
  import Model, { attr } from '@ember-data/model';
@@ -3931,7 +3601,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
3931
3601
  _initializerDefineProperty(this, "isReloading", _descriptor, this);
3932
3602
  }
3933
3603
  init(options = {}) {
3934
- if (macroCondition(isDevelopingApp())) {
3604
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
3935
3605
  if (!options._secretInit && !options._createProps) {
3936
3606
  throw new Error('You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.');
3937
3607
  }
@@ -3943,8 +3613,8 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
3943
3613
  let store = this.store = _secretInit.store;
3944
3614
  super.init(options);
3945
3615
  let identity = _secretInit.identifier;
3946
- _secretInit.cb(this, _secretInit.recordData, identity, _secretInit.store);
3947
- this.___recordState = macroCondition(isDevelopingApp()) ? new RecordState(this) : null;
3616
+ _secretInit.cb(this, _secretInit.cache, identity, _secretInit.store);
3617
+ this.___recordState = macroCondition(getOwnConfig().env.DEBUG) ? new RecordState(this) : null;
3948
3618
  this.setProperties(createProps);
3949
3619
  let notifications = store.notifications;
3950
3620
  this.___private_notifications = notifications.subscribe(identity, (identifier, type, key) => {
@@ -3954,7 +3624,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
3954
3624
  destroy() {
3955
3625
  const identifier = recordIdentifierFor(this);
3956
3626
  this.___recordState?.destroy();
3957
- const store = storeFor(this);
3627
+ const store = storeFor$1(this);
3958
3628
  store.notifications.unsubscribe(this.___private_notifications);
3959
3629
  // Legacy behavior is to notify the relationships on destroy
3960
3630
  // such that they "clear". It's uncertain this behavior would
@@ -4189,7 +3859,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4189
3859
  return this.currentState.isError;
4190
3860
  }
4191
3861
  set isError(v) {
4192
- if (macroCondition(isDevelopingApp())) {
3862
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
4193
3863
  throw new Error(`isError is not directly settable`);
4194
3864
  }
4195
3865
  }
@@ -4214,7 +3884,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4214
3884
  // this guard exists, because some dev-only deprecation code
4215
3885
  // (addListener via validatePropertyInjections) invokes toString before the
4216
3886
  // object is real.
4217
- if (macroCondition(isDevelopingApp())) {
3887
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
4218
3888
  try {
4219
3889
  return recordIdentifierFor(this).id;
4220
3890
  } catch {
@@ -4249,7 +3919,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4249
3919
  // when using legacy/classic ember classes. Basically: lazy in prod and eager in dev.
4250
3920
  // so we do this to try to steer folks to the nicer "dont user currentState"
4251
3921
  // error.
4252
- if (macroCondition(!isDevelopingApp())) {
3922
+ if (macroCondition(!getOwnConfig().env.DEBUG)) {
4253
3923
  if (!this.___recordState) {
4254
3924
  this.___recordState = new RecordState(this);
4255
3925
  }
@@ -4345,7 +4015,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4345
4015
  @return {Object} an object whose values are primitive JSON values only
4346
4016
  */
4347
4017
  serialize(options) {
4348
- return storeFor(this)._instanceCache.createSnapshot(recordIdentifierFor(this)).serialize(options);
4018
+ return storeFor$1(this).serializeRecord(this, options);
4349
4019
  }
4350
4020
 
4351
4021
  /*
@@ -4394,7 +4064,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4394
4064
  deleteRecord() {
4395
4065
  // ensure we've populated currentState prior to deleting a new record
4396
4066
  if (this.currentState) {
4397
- storeFor(this).deleteRecord(this);
4067
+ storeFor$1(this).deleteRecord(this);
4398
4068
  }
4399
4069
  }
4400
4070
 
@@ -4441,7 +4111,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4441
4111
  } = this.currentState;
4442
4112
  this.deleteRecord();
4443
4113
  if (isNew) {
4444
- return resolve(this);
4114
+ return Promise.resolve(this);
4445
4115
  }
4446
4116
  return this.save(options).then(_ => {
4447
4117
  run(() => {
@@ -4461,7 +4131,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4461
4131
  if (this.currentState.isNew && (this.isDestroyed || this.isDestroying)) {
4462
4132
  return;
4463
4133
  }
4464
- storeFor(this).unloadRecord(this);
4134
+ storeFor$1(this).unloadRecord(this);
4465
4135
  }
4466
4136
 
4467
4137
  /**
@@ -4517,7 +4187,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4517
4187
  and value is an [oldProp, newProp] array.
4518
4188
  */
4519
4189
  changedAttributes() {
4520
- return recordDataFor(this).changedAttrs(recordIdentifierFor(this));
4190
+ return peekCache(this).changedAttrs(recordIdentifierFor(this));
4521
4191
  }
4522
4192
 
4523
4193
  /**
@@ -4542,8 +4212,8 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4542
4212
  const {
4543
4213
  isNew
4544
4214
  } = currentState;
4545
- storeFor(this)._join(() => {
4546
- recordDataFor(this).rollbackAttrs(recordIdentifierFor(this));
4215
+ storeFor$1(this)._join(() => {
4216
+ peekCache(this).rollbackAttrs(recordIdentifierFor(this));
4547
4217
  this.errors.clear();
4548
4218
  currentState.cleanErrorRequests();
4549
4219
  if (isNew) {
@@ -4558,7 +4228,12 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4558
4228
  */
4559
4229
  // TODO @deprecate in favor of a public API or examples of how to test successfully
4560
4230
  _createSnapshot() {
4561
- return storeFor(this)._instanceCache.createSnapshot(recordIdentifierFor(this));
4231
+ const store = storeFor$1(this);
4232
+ if (!store._fetchManager) {
4233
+ const FetchManager = importSync('@ember-data/legacy-compat/-private').FetchManager;
4234
+ store._fetchManager = new FetchManager(store);
4235
+ }
4236
+ return store._fetchManager.createSnapshot(recordIdentifierFor(this));
4562
4237
  }
4563
4238
 
4564
4239
  /**
@@ -4598,9 +4273,9 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4598
4273
  save(options) {
4599
4274
  let promise;
4600
4275
  if (this.currentState.isNew && this.currentState.isDeleted) {
4601
- promise = resolve(this);
4276
+ promise = Promise.resolve(this);
4602
4277
  } else {
4603
- promise = storeFor(this).saveRecord(this, options);
4278
+ promise = storeFor$1(this).saveRecord(this, options);
4604
4279
  }
4605
4280
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_SAVE_PROMISE_ACCESS)) {
4606
4281
  return deprecatedPromiseObject(promise);
@@ -4631,16 +4306,22 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4631
4306
  adapter returns successfully or rejected if the adapter returns
4632
4307
  with an error.
4633
4308
  */
4634
- reload(_options) {
4635
- let options = {};
4636
- if (typeof _options === 'object' && _options !== null && _options.adapterOptions) {
4637
- options.adapterOptions = _options.adapterOptions;
4638
- }
4309
+ reload(options = {}) {
4639
4310
  options.isReloading = true;
4640
- let identifier = recordIdentifierFor(this);
4311
+ options.reload = true;
4312
+ const identifier = recordIdentifierFor(this);
4641
4313
  assert(`You cannot reload a record without an ID`, identifier.id);
4642
4314
  this.isReloading = true;
4643
- const promise = storeFor(this)._fetchManager.scheduleFetch(identifier, options).then(() => this).finally(() => {
4315
+ const promise = storeFor$1(this).request({
4316
+ op: 'findRecord',
4317
+ data: {
4318
+ options,
4319
+ record: identifier
4320
+ },
4321
+ cacheOptions: {
4322
+ [Symbol.for('ember-data:skip-cache')]: true
4323
+ }
4324
+ }).then(() => this).finally(() => {
4644
4325
  this.isReloading = false;
4645
4326
  });
4646
4327
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_SAVE_PROMISE_ACCESS)) {
@@ -4808,11 +4489,46 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4808
4489
  return this.constructor.relationshipsByName.get(name);
4809
4490
  }
4810
4491
  inverseFor(key) {
4811
- return this.constructor.inverseFor(key, storeFor(this));
4492
+ return this.constructor.inverseFor(key, storeFor$1(this));
4812
4493
  }
4813
4494
  eachAttribute(callback, binding) {
4814
4495
  this.constructor.eachAttribute(callback, binding);
4815
4496
  }
4497
+
4498
+ /**
4499
+ Create should only ever be called by the store. To create an instance of a
4500
+ `Model` in a dirty state use `store.createRecord`.
4501
+ To create instances of `Model` in a clean state, use `store.push`
4502
+ @method create
4503
+ @private
4504
+ @static
4505
+ */
4506
+ /**
4507
+ Represents the model's class name as a string. This can be used to look up the model's class name through
4508
+ `Store`'s modelFor method.
4509
+ `modelName` is generated for you by Ember Data. It will be a lowercased, dasherized string.
4510
+ For example:
4511
+ ```javascript
4512
+ store.modelFor('post').modelName; // 'post'
4513
+ store.modelFor('blog-post').modelName; // 'blog-post'
4514
+ ```
4515
+ The most common place you'll want to access `modelName` is in your serializer's `payloadKeyFromModelName` method. For example, to change payload
4516
+ keys to underscore (instead of dasherized), you might use the following code:
4517
+ ```javascript
4518
+ import RESTSerializer from '@ember-data/serializer/rest';
4519
+ import { underscore } from '<app-name>/utils/string-utils';
4520
+ export default const PostSerializer = RESTSerializer.extend({
4521
+ payloadKeyFromModelName(modelName) {
4522
+ return underscore(modelName);
4523
+ }
4524
+ });
4525
+ ```
4526
+ @property modelName
4527
+ @public
4528
+ @type String
4529
+ @readonly
4530
+ @static
4531
+ */
4816
4532
  /*
4817
4533
  These class methods below provide relationship
4818
4534
  introspection abilities about relationships.
@@ -4826,7 +4542,6 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4826
4542
  do it before using your model with the store, which uses these properties
4827
4543
  extensively.
4828
4544
  */
4829
-
4830
4545
  /**
4831
4546
  For a given relationship name, returns the model type of the relationship.
4832
4547
  For example, if you define a model like this:
@@ -4980,7 +4695,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4980
4695
  if (possibleRelationships.length === 0) {
4981
4696
  return null;
4982
4697
  }
4983
- if (macroCondition(isDevelopingApp())) {
4698
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
4984
4699
  let filteredRelationships = possibleRelationships.filter(possibleRelationship => {
4985
4700
  let optionsForRelationship = possibleRelationship.options;
4986
4701
  return name === optionsForRelationship.inverse;
@@ -4998,7 +4713,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
4998
4713
  }
4999
4714
 
5000
4715
  // ensure inverse is properly configured
5001
- if (macroCondition(isDevelopingApp())) {
4716
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
5002
4717
  if (isPolymorphic) {
5003
4718
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_NON_EXPLICIT_POLYMORPHISM)) {
5004
4719
  if (!inverseOptions.as) {
@@ -5020,7 +4735,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
5020
4735
  }
5021
4736
 
5022
4737
  // ensure we are properly configured
5023
- if (macroCondition(isDevelopingApp())) {
4738
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
5024
4739
  if (inverseOptions.polymorphic) {
5025
4740
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_NON_EXPLICIT_POLYMORPHISM)) {
5026
4741
  if (!options.as) {
@@ -5186,7 +4901,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
5186
4901
  import { get } from '@ember/object';
5187
4902
  import Blog from 'app/models/blog';
5188
4903
  let relatedTypes = Blog.relatedTypes');
5189
- //=> [ User, Post ]
4904
+ //=> ['user', 'post']
5190
4905
  ```
5191
4906
  @property relatedTypes
5192
4907
  @public
@@ -5274,7 +4989,7 @@ let Model = (_class = (_class2 = class Model extends EmberObject {
5274
4989
  for (let i = 0; i < relationships.length; i++) {
5275
4990
  let key = relationships[i];
5276
4991
  let value = rels[key];
5277
- map.set(value.key, value);
4992
+ map.set(value.name || value.key, value);
5278
4993
  }
5279
4994
  return map;
5280
4995
  }
@@ -5721,16 +5436,21 @@ if (macroCondition(getOwnConfig().includeDataAdapter)) {
5721
5436
  @private
5722
5437
  */
5723
5438
  Model.prototype._debugInfo = function () {
5724
- let attributes = ['id'];
5725
5439
  let relationships = {};
5726
5440
  let expensiveProperties = [];
5727
- this.eachAttribute((name, meta) => attributes.push(name));
5441
+ const identifier = recordIdentifierFor(this);
5442
+ const schema = this.store.getSchemaDefinitionService();
5443
+ const attrDefs = schema.attributesDefinitionFor(identifier);
5444
+ const relDefs = schema.relationshipsDefinitionFor(identifier);
5445
+ const attributes = Object.keys(attrDefs);
5446
+ attributes.unshift('id');
5728
5447
  let groups = [{
5729
5448
  name: 'Attributes',
5730
5449
  properties: attributes,
5731
5450
  expand: true
5732
5451
  }];
5733
- this.eachRelationship((name, relationship) => {
5452
+ Object.keys(relDefs).forEach(name => {
5453
+ const relationship = relDefs[name];
5734
5454
  let properties = relationships[relationship.kind];
5735
5455
  if (properties === undefined) {
5736
5456
  properties = relationships[relationship.kind] = [];
@@ -5758,7 +5478,7 @@ if (macroCondition(getOwnConfig().includeDataAdapter)) {
5758
5478
  };
5759
5479
  };
5760
5480
  }
5761
- if (macroCondition(isDevelopingApp())) {
5481
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
5762
5482
  let lookupDescriptor = function lookupDescriptor(obj, keyName) {
5763
5483
  let current = obj;
5764
5484
  do {
@@ -5861,6 +5581,7 @@ function normalizeType$1(type) {
5861
5581
  ```
5862
5582
 
5863
5583
  #### One-To-Many
5584
+
5864
5585
  To declare a one-to-many relationship between two models, use
5865
5586
  `belongsTo` in combination with `hasMany`, like this:
5866
5587
 
@@ -5868,7 +5589,7 @@ function normalizeType$1(type) {
5868
5589
  import Model, { hasMany } from '@ember-data/model';
5869
5590
 
5870
5591
  export default class PostModel extends Model {
5871
- @hasMany('comment') comments;
5592
+ @hasMany('comment', { async: false, inverse: 'post' }) comments;
5872
5593
  }
5873
5594
  ```
5874
5595
 
@@ -5876,23 +5597,10 @@ function normalizeType$1(type) {
5876
5597
  import Model, { belongsTo } from '@ember-data/model';
5877
5598
 
5878
5599
  export default class CommentModel extends Model {
5879
- @belongsTo('post') post;
5880
- }
5881
- ```
5882
-
5883
- You can avoid passing a string as the first parameter. In that case Ember Data
5884
- will infer the type from the key name.
5885
-
5886
- ```app/models/comment.js
5887
- import Model, { belongsTo } from '@ember-data/model';
5888
-
5889
- export default class CommentModel extends Model {
5890
- @belongsTo post;
5600
+ @belongsTo('post', { async: false, inverse: 'comments' }) post;
5891
5601
  }
5892
5602
  ```
5893
5603
 
5894
- will lookup for a Post type.
5895
-
5896
5604
  #### Sync relationships
5897
5605
 
5898
5606
  Ember Data resolves sync relationships with the related resources
@@ -5904,7 +5612,8 @@ function normalizeType$1(type) {
5904
5612
 
5905
5613
  export default class CommentModel extends Model {
5906
5614
  @belongsTo('post', {
5907
- async: false
5615
+ async: false,
5616
+ inverse: null
5908
5617
  })
5909
5618
  post;
5910
5619
  }
@@ -6007,7 +5716,7 @@ function belongsTo(modelName, options) {
6007
5716
  return null;
6008
5717
  }
6009
5718
  const support = lookupLegacySupport(this);
6010
- if (macroCondition(isDevelopingApp())) {
5719
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
6011
5720
  if (['currentState'].indexOf(key) !== -1) {
6012
5721
  throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your belongsTo on ${this.constructor.toString()}`);
6013
5722
  }
@@ -6026,7 +5735,7 @@ function belongsTo(modelName, options) {
6026
5735
  },
6027
5736
  set(key, value) {
6028
5737
  const support = lookupLegacySupport(this);
6029
- if (macroCondition(isDevelopingApp())) {
5738
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
6030
5739
  if (['currentState'].indexOf(key) !== -1) {
6031
5740
  throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your belongsTo on ${this.constructor.toString()}`);
6032
5741
  }
@@ -6257,7 +5966,7 @@ function hasMany(type, options) {
6257
5966
  };
6258
5967
  return computed({
6259
5968
  get(key) {
6260
- if (macroCondition(isDevelopingApp())) {
5969
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
6261
5970
  if (['currentState'].indexOf(key) !== -1) {
6262
5971
  throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your hasMany on ${this.constructor.toString()}`);
6263
5972
  }
@@ -6268,7 +5977,7 @@ function hasMany(type, options) {
6268
5977
  return lookupLegacySupport(this).getHasMany(key);
6269
5978
  },
6270
5979
  set(key, records) {
6271
- if (macroCondition(isDevelopingApp())) {
5980
+ if (macroCondition(getOwnConfig().env.DEBUG)) {
6272
5981
  if (['currentState'].indexOf(key) !== -1) {
6273
5982
  throw new Error(`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your hasMany on ${this.constructor.toString()}`);
6274
5983
  }