@ember-data/model 4.6.1 → 4.7.0

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.
@@ -11,19 +11,6 @@ import { computedMacroWithOptionalParams } from './util';
11
11
  @module @ember-data/model
12
12
  */
13
13
 
14
- function getDefaultValue(record, options, key) {
15
- if (typeof options.defaultValue === 'function') {
16
- return options.defaultValue.apply(null, arguments);
17
- } else {
18
- let defaultValue = options.defaultValue;
19
- assert(
20
- `Non primitive defaultValues are not supported because they are shared between all instances. If you would like to use a complex object as a default value please provide a function that returns the complex object.`,
21
- typeof defaultValue !== 'object' || defaultValue === null
22
- );
23
- return defaultValue;
24
- }
25
- }
26
-
27
14
  /**
28
15
  `attr` defines an attribute on a [Model](/ember-data/release/classes/Model).
29
16
  By default, attributes are passed through as-is, however you can specify an
@@ -123,29 +110,26 @@ function attr(type, options) {
123
110
  let meta = {
124
111
  type: type,
125
112
  isAttribute: true,
126
- kind: 'attribute',
127
113
  options: options,
128
114
  };
129
115
 
130
116
  return computed({
131
117
  get(key) {
132
118
  if (DEBUG) {
133
- if (['_internalModel', 'currentState'].indexOf(key) !== -1) {
119
+ if (['currentState'].indexOf(key) !== -1) {
134
120
  throw new Error(
135
121
  `'${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()}`
136
122
  );
137
123
  }
138
124
  }
139
- let recordData = recordDataFor(this);
140
- if (recordData.hasAttr(key)) {
141
- return recordData.getAttr(key);
142
- } else {
143
- return getDefaultValue(this, options, key);
125
+ if (this.isDestroyed || this.isDestroying) {
126
+ return;
144
127
  }
128
+ return recordDataFor(this).getAttr(recordIdentifierFor(this), key);
145
129
  },
146
130
  set(key, value) {
147
131
  if (DEBUG) {
148
- if (['_internalModel', 'currentState'].indexOf(key) !== -1) {
132
+ if (['currentState'].indexOf(key) !== -1) {
149
133
  throw new Error(
150
134
  `'${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()}`
151
135
  );
@@ -155,10 +139,11 @@ function attr(type, options) {
155
139
  `Attempted to set '${key}' on the deleted record ${recordIdentifierFor(this)}`,
156
140
  !this.currentState.isDeleted
157
141
  );
158
- const recordData = storeFor(this)._instanceCache.getRecordData(recordIdentifierFor(this));
159
- let currentValue = recordData.getAttr(key);
142
+ const identifier = recordIdentifierFor(this);
143
+ const recordData = storeFor(this)._instanceCache.getRecordData(identifier);
144
+ let currentValue = recordData.getAttr(identifier, key);
160
145
  if (currentValue !== value) {
161
- recordData.setDirtyAttribute(key, value);
146
+ recordData.setAttr(identifier, key, value);
162
147
 
163
148
  if (!this.isValid) {
164
149
  const { errors } = this;
@@ -1,10 +1,24 @@
1
- import { assert, inspect, warn } from '@ember/debug';
1
+ import { assert, deprecate, warn } from '@ember/debug';
2
2
  import { computed } from '@ember/object';
3
+ import { dasherize } from '@ember/string';
3
4
  import { DEBUG } from '@glimmer/env';
4
5
 
5
- import { LEGACY_SUPPORT } from './model';
6
+ import {
7
+ DEPRECATE_RELATIONSHIPS_WITHOUT_ASYNC,
8
+ DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE,
9
+ DEPRECATE_RELATIONSHIPS_WITHOUT_TYPE,
10
+ } from '@ember-data/private-build-infra/deprecations';
11
+
12
+ import { lookupLegacySupport } from './model';
6
13
  import { computedMacroWithOptionalParams } from './util';
7
14
 
15
+ function normalizeType(type) {
16
+ if (DEPRECATE_RELATIONSHIPS_WITHOUT_TYPE && !type) {
17
+ return;
18
+ }
19
+
20
+ return dasherize(type);
21
+ }
8
22
  /**
9
23
  @module @ember-data/model
10
24
  */
@@ -98,7 +112,7 @@ import { computedMacroWithOptionalParams } from './util';
98
112
  a related resource is known to exist and it has not been loaded.
99
113
 
100
114
  ```
101
- let post = comment.get('post');
115
+ let post = comment.post;
102
116
 
103
117
  ```
104
118
 
@@ -111,29 +125,71 @@ import { computedMacroWithOptionalParams } from './util';
111
125
  @return {Ember.computed} relationship
112
126
  */
113
127
  function belongsTo(modelName, options) {
114
- let opts, userEnteredModelName;
115
- if (typeof modelName === 'object') {
116
- opts = modelName;
117
- userEnteredModelName = undefined;
118
- } else {
119
- opts = options;
120
- userEnteredModelName = modelName;
128
+ let opts = options;
129
+ let userEnteredModelName = modelName;
130
+ if (DEPRECATE_RELATIONSHIPS_WITHOUT_TYPE && (typeof modelName !== 'string' || !modelName.length)) {
131
+ deprecate('belongsTo() must specify the string type of the related resource as the first parameter', false, {
132
+ id: 'ember-data:deprecate-non-strict-relationships',
133
+ for: 'ember-data',
134
+ until: '5.0',
135
+ since: { enabled: '4.8', available: '4.8' },
136
+ });
137
+
138
+ if (typeof modelName === 'object') {
139
+ opts = modelName;
140
+ userEnteredModelName = undefined;
141
+ } else {
142
+ opts = options;
143
+ userEnteredModelName = modelName;
144
+ }
145
+
146
+ assert(
147
+ 'The first argument to belongsTo must be a string representing a model type key, not an instance of ' +
148
+ typeof userEnteredModelName +
149
+ ". E.g., to define a relation to the Person model, use belongsTo('person')",
150
+ typeof userEnteredModelName === 'string' || typeof userEnteredModelName === 'undefined'
151
+ );
121
152
  }
122
153
 
123
- assert(
124
- 'The first argument to belongsTo must be a string representing a model type key, not an instance of ' +
125
- inspect(userEnteredModelName) +
126
- ". E.g., to define a relation to the Person model, use belongsTo('person')",
127
- typeof userEnteredModelName === 'string' || typeof userEnteredModelName === 'undefined'
128
- );
154
+ if (DEPRECATE_RELATIONSHIPS_WITHOUT_ASYNC && (!opts || typeof opts.async !== 'boolean')) {
155
+ opts = opts || {};
156
+ if (!('async' in opts)) {
157
+ opts.async = true;
158
+ }
159
+ deprecate('belongsTo(<type>, <options>) must specify options.async as either `true` or `false`.', false, {
160
+ id: 'ember-data:deprecate-non-strict-relationships',
161
+ for: 'ember-data',
162
+ until: '5.0',
163
+ since: { enabled: '4.8', available: '4.8' },
164
+ });
165
+ } else {
166
+ assert(`Expected belongsTo options.async to be a boolean`, opts && typeof opts.async === 'boolean');
167
+ }
129
168
 
130
- opts = opts || {};
131
- if (!('async' in opts)) {
132
- opts.async = true;
169
+ if (
170
+ DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE &&
171
+ opts.inverse !== null &&
172
+ (typeof opts.inverse !== 'string' || opts.inverse.length === 0)
173
+ ) {
174
+ deprecate(
175
+ 'belongsTo(<type>, <options>) must specify options.inverse as either `null` or string type of the related resource.',
176
+ false,
177
+ {
178
+ id: 'ember-data:deprecate-non-strict-relationships',
179
+ for: 'ember-data',
180
+ until: '5.0',
181
+ since: { enabled: '4.8', available: '4.8' },
182
+ }
183
+ );
184
+ } else {
185
+ assert(
186
+ `Expected belongsTo options.inverse to be either null or the string type of the related resource.`,
187
+ opts.inverse === null || (typeof opts.inverse === 'string' && opts.inverse.length > 0)
188
+ );
133
189
  }
134
190
 
135
191
  let meta = {
136
- type: userEnteredModelName,
192
+ type: normalizeType(userEnteredModelName),
137
193
  isRelationship: true,
138
194
  options: opts,
139
195
  kind: 'belongsTo',
@@ -143,10 +199,16 @@ function belongsTo(modelName, options) {
143
199
 
144
200
  return computed({
145
201
  get(key) {
146
- const support = LEGACY_SUPPORT.lookup(this);
202
+ // this is a legacy behavior we may not carry into a new model setup
203
+ // it's better to error on disconnected records so users find errors
204
+ // in their logic.
205
+ if (this.isDestroying || this.isDestroyed) {
206
+ return null;
207
+ }
208
+ const support = lookupLegacySupport(this);
147
209
 
148
210
  if (DEBUG) {
149
- if (['_internalModel', 'recordData', 'currentState'].indexOf(key) !== -1) {
211
+ if (['currentState'].indexOf(key) !== -1) {
150
212
  throw new Error(
151
213
  `'${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()}`
152
214
  );
@@ -175,15 +237,15 @@ function belongsTo(modelName, options) {
175
237
  return support.getBelongsTo(key);
176
238
  },
177
239
  set(key, value) {
178
- const support = LEGACY_SUPPORT.lookup(this);
240
+ const support = lookupLegacySupport(this);
179
241
  if (DEBUG) {
180
- if (['_internalModel', 'recordData', 'currentState'].indexOf(key) !== -1) {
242
+ if (['currentState'].indexOf(key) !== -1) {
181
243
  throw new Error(
182
244
  `'${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()}`
183
245
  );
184
246
  }
185
247
  }
186
- this.store._backburner.join(() => {
248
+ this.store._join(() => {
187
249
  support.setDirtyBelongsTo(key, value);
188
250
  });
189
251
 
@@ -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
+ }
@@ -123,7 +123,7 @@ export default class Errors extends ArrayProxyWithCustomOverrides<ValidationErro
123
123
  email: 'invalidEmail'
124
124
  });
125
125
  user.save().catch(function(){
126
- user.get('errors').errorsFor('email'); // returns:
126
+ user.errors.errorsFor('email'); // returns:
127
127
  // [{attribute: "email", message: "Doesn't look like a valid email."}]
128
128
  });
129
129
  ```
@@ -219,7 +219,7 @@ export default class Errors extends ArrayProxyWithCustomOverrides<ValidationErro
219
219
 
220
220
  Example
221
221
  ```javascript
222
- let errors = get(user, 'errors');
222
+ let errors = user.errors;
223
223
 
224
224
  // add multiple errors
225
225
  errors.add('password', [
@@ -293,7 +293,7 @@ export default class Errors extends ArrayProxyWithCustomOverrides<ValidationErro
293
293
  Example:
294
294
 
295
295
  ```javascript
296
- let errors = get('user', errors);
296
+ let errors = user.errors;
297
297
  errors.add('phone', ['error-1', 'error-2']);
298
298
 
299
299
  errors.errorsFor('phone');
@@ -344,7 +344,7 @@ export default class Errors extends ArrayProxyWithCustomOverrides<ValidationErro
344
344
  Example:
345
345
 
346
346
  ```javascript
347
- let errors = get('user', errors);
347
+ let errors = user.errors;
348
348
  errors.add('username', ['error-a']);
349
349
  errors.add('phone', ['error-1', 'error-2']);
350
350
 
@@ -369,7 +369,7 @@ export default class Errors extends ArrayProxyWithCustomOverrides<ValidationErro
369
369
  errors.errorsFor('phone');
370
370
  // => undefined
371
371
 
372
- errors.get('messages')
372
+ errors.messages
373
373
  // => []
374
374
  ```
375
375
  @method clear
@@ -406,7 +406,7 @@ export default class Errors extends ArrayProxyWithCustomOverrides<ValidationErro
406
406
  export default class UserEditController extends Controller {
407
407
  @action
408
408
  save(user) {
409
- if (user.get('errors').has('email')) {
409
+ if (user.errors.has('email')) {
410
410
  return alert('Please update your email before attempting to save.');
411
411
  }
412
412
  user.save();
@@ -1,13 +1,31 @@
1
1
  /**
2
2
  @module @ember-data/model
3
3
  */
4
- import { assert, inspect } from '@ember/debug';
4
+ import { A } from '@ember/array';
5
+ import { assert, deprecate, inspect } from '@ember/debug';
5
6
  import { computed } from '@ember/object';
7
+ import { dasherize } from '@ember/string';
6
8
  import { DEBUG } from '@glimmer/env';
7
9
 
8
- import { LEGACY_SUPPORT } from './model';
10
+ import { singularize } from 'ember-inflector';
11
+
12
+ import {
13
+ DEPRECATE_RELATIONSHIPS_WITHOUT_ASYNC,
14
+ DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE,
15
+ DEPRECATE_RELATIONSHIPS_WITHOUT_TYPE,
16
+ } from '@ember-data/private-build-infra/deprecations';
17
+
18
+ import { lookupLegacySupport } from './model';
9
19
  import { computedMacroWithOptionalParams } from './util';
10
20
 
21
+ function normalizeType(type) {
22
+ if (DEPRECATE_RELATIONSHIPS_WITHOUT_TYPE && !type) {
23
+ return;
24
+ }
25
+
26
+ return singularize(dasherize(type));
27
+ }
28
+
11
29
  /**
12
30
  `hasMany` is used to define One-To-Many and Many-To-Many
13
31
  relationships on a [Model](/ember-data/release/classes/Model).
@@ -132,7 +150,7 @@ import { computedMacroWithOptionalParams } from './util';
132
150
  when any of the known related resources have not been loaded.
133
151
 
134
152
  ```
135
- post.get('comments').forEach((comment) => {
153
+ post.comments.forEach((comment) => {
136
154
 
137
155
  });
138
156
 
@@ -150,21 +168,60 @@ import { computedMacroWithOptionalParams } from './util';
150
168
  @return {Ember.computed} relationship
151
169
  */
152
170
  function hasMany(type, options) {
153
- if (typeof type === 'object') {
154
- options = type;
155
- type = undefined;
171
+ if (DEPRECATE_RELATIONSHIPS_WITHOUT_TYPE && (typeof type !== 'string' || !type.length)) {
172
+ deprecate(
173
+ 'hasMany(<type>, <options>) must specify the string type of the related resource as the first parameter',
174
+ false,
175
+ {
176
+ id: 'ember-data:deprecate-non-strict-relationships',
177
+ for: 'ember-data',
178
+ until: '5.0',
179
+ since: { enabled: '4.8', available: '4.8' },
180
+ }
181
+ );
182
+ if (typeof type === 'object') {
183
+ options = type;
184
+ type = undefined;
185
+ }
186
+
187
+ assert(
188
+ `The first argument to hasMany must be a string representing a model type key, not an instance of ${inspect(
189
+ type
190
+ )}. E.g., to define a relation to the Comment model, use hasMany('comment')`,
191
+ typeof type === 'string' || typeof type === 'undefined'
192
+ );
156
193
  }
157
194
 
158
- assert(
159
- `The first argument to hasMany must be a string representing a model type key, not an instance of ${inspect(
160
- type
161
- )}. E.g., to define a relation to the Comment model, use hasMany('comment')`,
162
- typeof type === 'string' || typeof type === 'undefined'
163
- );
195
+ if (DEPRECATE_RELATIONSHIPS_WITHOUT_ASYNC && (!options || typeof options.async !== 'boolean')) {
196
+ options = options || {};
197
+ if (!('async' in options)) {
198
+ options.async = true;
199
+ }
200
+ deprecate('hasMany(<type>, <options>) must specify options.async as either `true` or `false`.', false, {
201
+ id: 'ember-data:deprecate-non-strict-relationships',
202
+ for: 'ember-data',
203
+ until: '5.0',
204
+ since: { enabled: '4.8', available: '4.8' },
205
+ });
206
+ } else {
207
+ assert(`Expected hasMany options.async to be a boolean`, options && typeof options.async === 'boolean');
208
+ }
164
209
 
165
- options = options || {};
166
- if (!('async' in options)) {
167
- options.async = true;
210
+ if (
211
+ DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE &&
212
+ options.inverse !== null &&
213
+ (typeof options.inverse !== 'string' || options.inverse.length === 0)
214
+ ) {
215
+ deprecate(
216
+ 'hasMany(<type>, <options>) must specify options.inverse as either `null` or string type of the related resource.',
217
+ false,
218
+ {
219
+ id: 'ember-data:deprecate-non-strict-relationships',
220
+ for: 'ember-data',
221
+ until: '5.0',
222
+ since: { enabled: '4.8', available: '4.8' },
223
+ }
224
+ );
168
225
  }
169
226
 
170
227
  // Metadata about relationships is stored on the meta of
@@ -172,7 +229,7 @@ function hasMany(type, options) {
172
229
  // serialization. Note that `key` is populated lazily
173
230
  // the first time the CP is called.
174
231
  let meta = {
175
- type,
232
+ type: normalizeType(type),
176
233
  options,
177
234
  isRelationship: true,
178
235
  kind: 'hasMany',
@@ -183,25 +240,30 @@ function hasMany(type, options) {
183
240
  return computed({
184
241
  get(key) {
185
242
  if (DEBUG) {
186
- if (['_internalModel', 'currentState'].indexOf(key) !== -1) {
243
+ if (['currentState'].indexOf(key) !== -1) {
187
244
  throw new Error(
188
245
  `'${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()}`
189
246
  );
190
247
  }
191
248
  }
192
- return LEGACY_SUPPORT.lookup(this).getHasMany(key);
249
+ if (this.isDestroying || this.isDestroyed) {
250
+ return A();
251
+ }
252
+ return lookupLegacySupport(this).getHasMany(key);
193
253
  },
194
254
  set(key, records) {
195
255
  if (DEBUG) {
196
- if (['_internalModel', 'currentState'].indexOf(key) !== -1) {
256
+ if (['currentState'].indexOf(key) !== -1) {
197
257
  throw new Error(
198
258
  `'${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()}`
199
259
  );
200
260
  }
201
261
  }
202
- const support = LEGACY_SUPPORT.lookup(this);
203
- this.store._backburner.join(() => {
204
- support.setDirtyHasMany(key, records);
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));
265
+ this.store._join(() => {
266
+ manyArray.splice(0, manyArray.length, ...records);
205
267
  });
206
268
 
207
269
  return support.getHasMany(key);
@@ -3,11 +3,15 @@ import { DEBUG } from '@glimmer/env';
3
3
 
4
4
  import { resolve } from 'rsvp';
5
5
 
6
- import { DEPRECATE_RSVP_PROMISE } from '@ember-data/private-build-infra/deprecations';
6
+ import {
7
+ DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE,
8
+ DEPRECATE_RSVP_PROMISE,
9
+ } from '@ember-data/private-build-infra/deprecations';
7
10
 
8
11
  import { iterateData, normalizeResponseHelper } from './legacy-data-utils';
9
12
 
10
13
  export function _findHasMany(adapter, store, identifier, link, relationship, options) {
14
+ const record = store._instanceCache.getRecord(identifier);
11
15
  const snapshot = store._instanceCache.createSnapshot(identifier, options);
12
16
  let modelClass = store.modelFor(relationship.type);
13
17
  let useLink = !link || typeof link === 'string';
@@ -18,7 +22,7 @@ export function _findHasMany(adapter, store, identifier, link, relationship, opt
18
22
  promise = guardDestroyedStore(promise, store, label);
19
23
  promise = promise.then(
20
24
  (adapterPayload) => {
21
- if (!_objectIsAlive(store._instanceCache.getInternalModel(identifier))) {
25
+ if (!_objectIsAlive(record)) {
22
26
  if (DEPRECATE_RSVP_PROMISE) {
23
27
  deprecate(
24
28
  `A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`,
@@ -57,13 +61,14 @@ export function _findHasMany(adapter, store, identifier, link, relationship, opt
57
61
  );
58
62
 
59
63
  if (DEPRECATE_RSVP_PROMISE) {
60
- promise = _guard(promise, _bind(_objectIsAlive, store._instanceCache.getInternalModel(identifier)));
64
+ promise = _guard(promise, _bind(_objectIsAlive, record));
61
65
  }
62
66
 
63
67
  return promise;
64
68
  }
65
69
 
66
70
  export function _findBelongsTo(store, identifier, link, relationship, options) {
71
+ const record = store._instanceCache.getRecord(identifier);
67
72
  let adapter = store.adapterFor(identifier.type);
68
73
 
69
74
  assert(`You tried to load a belongsTo relationship but you have no adapter (for ${identifier.type})`, adapter);
@@ -79,11 +84,11 @@ export function _findBelongsTo(store, identifier, link, relationship, options) {
79
84
  let label = `DS: Handle Adapter#findBelongsTo of ${identifier.type} : ${relationship.type}`;
80
85
 
81
86
  promise = guardDestroyedStore(promise, store, label);
82
- promise = _guard(promise, _bind(_objectIsAlive, store._instanceCache.getInternalModel(identifier)));
87
+ promise = _guard(promise, _bind(_objectIsAlive, record));
83
88
 
84
89
  promise = promise.then(
85
90
  (adapterPayload) => {
86
- if (!_objectIsAlive(store._instanceCache.getInternalModel(identifier))) {
91
+ if (!_objectIsAlive(record)) {
87
92
  if (DEPRECATE_RSVP_PROMISE) {
88
93
  deprecate(
89
94
  `A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`,
@@ -123,7 +128,7 @@ export function _findBelongsTo(store, identifier, link, relationship, options) {
123
128
  );
124
129
 
125
130
  if (DEPRECATE_RSVP_PROMISE) {
126
- promise = _guard(promise, _bind(_objectIsAlive, store._instanceCache.getInternalModel(identifier)));
131
+ promise = _guard(promise, _bind(_objectIsAlive, record));
127
132
  }
128
133
 
129
134
  return promise;
@@ -229,19 +234,36 @@ function ensureRelationshipIsSetToParent(payload, parentIdentifier, store, paren
229
234
  }
230
235
  }
231
236
 
232
- function getInverse(store, parentInternalModel, parentRelationship, type) {
233
- return recordDataFindInverseRelationshipInfo(store, parentInternalModel, parentRelationship, type);
237
+ function metaIsRelationshipDefinition(meta) {
238
+ return typeof meta._inverseKey === 'function';
234
239
  }
235
240
 
236
- function recordDataFindInverseRelationshipInfo(store, parentIdentifier, parentRelationship, type) {
241
+ function inverseForRelationship(store, identifier, key) {
242
+ const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor(identifier)[key];
243
+ if (!definition) {
244
+ return null;
245
+ }
246
+
247
+ if (DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE && metaIsRelationshipDefinition(definition)) {
248
+ const modelClass = store.modelFor(identifier.type);
249
+ return definition._inverseKey(store, modelClass);
250
+ }
251
+ assert(
252
+ `Expected the relationship defintion to specify the inverse type or null.`,
253
+ definition.options?.inverse === null ||
254
+ (typeof definition.options?.inverse === 'string' && definition.options.inverse.length > 0)
255
+ );
256
+ return definition.options.inverse;
257
+ }
258
+
259
+ function getInverse(store, parentIdentifier, parentRelationship, type) {
237
260
  let { name: lhs_relationshipName } = parentRelationship;
238
261
  let { type: parentType } = parentIdentifier;
239
- let inverseKey = store._instanceCache._storeWrapper.inverseForRelationship(parentType, lhs_relationshipName);
262
+ let inverseKey = inverseForRelationship(store, { type: parentType }, lhs_relationshipName);
240
263
 
241
264
  if (inverseKey) {
242
- let {
243
- meta: { kind },
244
- } = store._instanceCache._storeWrapper.relationshipsDefinitionFor(type)[inverseKey];
265
+ const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor({ type });
266
+ let { kind } = definition[inverseKey];
245
267
  return {
246
268
  inverseKey,
247
269
  kind,
@@ -2,7 +2,7 @@ import { assert } from '@ember/debug';
2
2
  import { DEBUG } from '@glimmer/env';
3
3
 
4
4
  import type Store from '@ember-data/store';
5
- import type ShimModelClass from '@ember-data/store/-private/model/shim-model-class';
5
+ import type ShimModelClass from '@ember-data/store/-private/legacy-model-support/shim-model-class';
6
6
  import type { JsonApiDocument } from '@ember-data/types/q/ember-data-json-api';
7
7
  import type { StableExistingRecordIdentifier, StableRecordIdentifier } from '@ember-data/types/q/identifier';
8
8
  import type { AdapterPayload } from '@ember-data/types/q/minimum-adapter-interface';