@ember-data/model 4.10.0 → 4.12.0-alpha.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.
Files changed (40) hide show
  1. package/addon/{-private/diff-array.ts → -private.js} +41 -13
  2. package/addon/-private.js.map +1 -0
  3. package/addon/has-many-a275fe0d.js +6283 -0
  4. package/addon/has-many-a275fe0d.js.map +1 -0
  5. package/addon/index.js +1 -0
  6. package/addon/index.js.map +1 -0
  7. package/addon-main.js +90 -0
  8. package/package.json +43 -15
  9. package/addon/-private/attr.js +0 -162
  10. package/addon/-private/belongs-to.js +0 -268
  11. package/addon/-private/debug/assert-polymorphic-type.js +0 -71
  12. package/addon/-private/deprecated-promise-proxy.ts +0 -76
  13. package/addon/-private/errors.ts +0 -425
  14. package/addon/-private/has-many.js +0 -280
  15. package/addon/-private/index.ts +0 -14
  16. package/addon/-private/legacy-data-fetch.js +0 -395
  17. package/addon/-private/legacy-data-utils.ts +0 -92
  18. package/addon/-private/legacy-relationships-support.ts +0 -774
  19. package/addon/-private/many-array.ts +0 -401
  20. package/addon/-private/model-for-mixin.ts +0 -38
  21. package/addon/-private/model.js +0 -2516
  22. package/addon/-private/notify-changes.ts +0 -72
  23. package/addon/-private/promise-belongs-to.ts +0 -73
  24. package/addon/-private/promise-many-array.ts +0 -425
  25. package/addon/-private/promise-proxy-base.js +0 -4
  26. package/addon/-private/record-state.ts +0 -468
  27. package/addon/-private/references/belongs-to.ts +0 -624
  28. package/addon/-private/references/has-many.ts +0 -669
  29. package/addon/-private/relationship-meta.ts +0 -98
  30. package/addon/-private/util.ts +0 -31
  31. package/addon/index.ts +0 -39
  32. package/blueprints/model/HELP.md +0 -26
  33. package/blueprints/model/files/__root__/__path__/__name__.js +0 -5
  34. package/blueprints/model/index.js +0 -158
  35. package/blueprints/model/native-files/__root__/__path__/__name__.js +0 -5
  36. package/blueprints/model-test/index.js +0 -33
  37. package/blueprints/model-test/mocha-files/__root__/__path__/__test__.js +0 -18
  38. package/blueprints/model-test/mocha-rfc-232-files/__root__/__path__/__test__.js +0 -15
  39. package/blueprints/model-test/qunit-files/__root__/__path__/__test__.js +0 -14
  40. package/index.js +0 -46
@@ -1,280 +0,0 @@
1
- /**
2
- @module @ember-data/model
3
- */
4
- import { A } from '@ember/array';
5
- import { assert, deprecate, inspect } from '@ember/debug';
6
- import { computed } from '@ember/object';
7
- import { dasherize } from '@ember/string';
8
- import { DEBUG } from '@glimmer/env';
9
-
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';
19
- import { computedMacroWithOptionalParams } from './util';
20
-
21
- function normalizeType(type) {
22
- if (DEPRECATE_RELATIONSHIPS_WITHOUT_TYPE) {
23
- if (!type) {
24
- return;
25
- }
26
- }
27
-
28
- return singularize(dasherize(type));
29
- }
30
-
31
- /**
32
- `hasMany` is used to define One-To-Many and Many-To-Many
33
- relationships on a [Model](/ember-data/release/classes/Model).
34
-
35
- `hasMany` takes an optional hash as a second parameter, currently
36
- supported options are:
37
-
38
- - `async`: A boolean value used to explicitly declare this to be an async relationship. The default is true.
39
- - `inverse`: A string used to identify the inverse property on a related model.
40
- - `polymorphic` A boolean value to mark the relationship as polymorphic
41
-
42
- #### One-To-Many
43
- To declare a one-to-many relationship between two models, use
44
- `belongsTo` in combination with `hasMany`, like this:
45
-
46
- ```app/models/post.js
47
- import Model, { hasMany } from '@ember-data/model';
48
-
49
- export default class PostModel extends Model {
50
- @hasMany('comment') comments;
51
- }
52
- ```
53
-
54
- ```app/models/comment.js
55
- import Model, { belongsTo } from '@ember-data/model';
56
-
57
- export default class CommentModel extends Model {
58
- @belongsTo('post') post;
59
- }
60
- ```
61
-
62
- #### Many-To-Many
63
- To declare a many-to-many relationship between two models, use
64
- `hasMany`:
65
-
66
- ```app/models/post.js
67
- import Model, { hasMany } from '@ember-data/model';
68
-
69
- export default class PostModel extends Model {
70
- @hasMany('tag') tags;
71
- }
72
- ```
73
-
74
- ```app/models/tag.js
75
- import Model, { hasMany } from '@ember-data/model';
76
-
77
- export default class TagModel extends Model {
78
- @hasMany('post') posts;
79
- }
80
- ```
81
-
82
- You can avoid passing a string as the first parameter. In that case Ember Data
83
- will infer the type from the singularized key name.
84
-
85
- ```app/models/post.js
86
- import Model, { hasMany } from '@ember-data/model';
87
-
88
- export default class PostModel extends Model {
89
- @hasMany tags;
90
- }
91
- ```
92
-
93
- will lookup for a Tag type.
94
-
95
- #### Explicit Inverses
96
-
97
- Ember Data will do its best to discover which relationships map to
98
- one another. In the one-to-many code above, for example, Ember Data
99
- can figure out that changing the `comments` relationship should update
100
- the `post` relationship on the inverse because post is the only
101
- relationship to that model.
102
-
103
- However, sometimes you may have multiple `belongsTo`/`hasMany` for the
104
- same type. You can specify which property on the related model is
105
- the inverse using `hasMany`'s `inverse` option:
106
-
107
- ```app/models/comment.js
108
- import Model, { belongsTo } from '@ember-data/model';
109
-
110
- export default class CommentModel extends Model {
111
- @belongsTo('post') onePost;
112
- @belongsTo('post') twoPost
113
- @belongsTo('post') redPost;
114
- @belongsTo('post') bluePost;
115
- }
116
- ```
117
-
118
- ```app/models/post.js
119
- import Model, { hasMany } from '@ember-data/model';
120
-
121
- export default class PostModel extends Model {
122
- @hasMany('comment', {
123
- inverse: 'redPost'
124
- })
125
- comments;
126
- }
127
- ```
128
-
129
- You can also specify an inverse on a `belongsTo`, which works how
130
- you'd expect.
131
-
132
- #### Sync relationships
133
-
134
- Ember Data resolves sync relationships with the related resources
135
- available in its local store, hence it is expected these resources
136
- to be loaded before or along-side the primary resource.
137
-
138
- ```app/models/post.js
139
- import Model, { hasMany } from '@ember-data/model';
140
-
141
- export default class PostModel extends Model {
142
- @hasMany('comment', {
143
- async: false
144
- })
145
- comments;
146
- }
147
- ```
148
-
149
- In contrast to async relationship, accessing a sync relationship
150
- will always return a [ManyArray](/ember-data/release/classes/ManyArray) instance
151
- containing the existing local resources. But it will error on access
152
- when any of the known related resources have not been loaded.
153
-
154
- ```
155
- post.comments.forEach((comment) => {
156
-
157
- });
158
-
159
- ```
160
-
161
- If you are using `links` with sync relationships, you have to use
162
- `ref.reload` to fetch the resources.
163
-
164
- @method hasMany
165
- @public
166
- @static
167
- @for @ember-data/model
168
- @param {String} type (optional) type of the relationship
169
- @param {Object} options (optional) a hash of options
170
- @return {Ember.computed} relationship
171
- */
172
- function hasMany(type, options) {
173
- if (DEPRECATE_RELATIONSHIPS_WITHOUT_TYPE) {
174
- if (typeof type !== 'string' || !type.length) {
175
- deprecate(
176
- 'hasMany(<type>, <options>) must specify the string type of the related resource as the first parameter',
177
- false,
178
- {
179
- id: 'ember-data:deprecate-non-strict-relationships',
180
- for: 'ember-data',
181
- until: '5.0',
182
- since: { enabled: '4.7', available: '4.7' },
183
- }
184
- );
185
- if (typeof type === 'object') {
186
- options = type;
187
- type = undefined;
188
- }
189
-
190
- assert(
191
- `The first argument to hasMany must be a string representing a model type key, not an instance of ${inspect(
192
- type
193
- )}. E.g., to define a relation to the Comment model, use hasMany('comment')`,
194
- typeof type === 'string' || typeof type === 'undefined'
195
- );
196
- }
197
- }
198
-
199
- if (DEPRECATE_RELATIONSHIPS_WITHOUT_ASYNC) {
200
- if (!options || typeof options.async !== 'boolean') {
201
- options = options || {};
202
- if (!('async' in options)) {
203
- options.async = true;
204
- }
205
- deprecate('hasMany(<type>, <options>) must specify options.async as either `true` or `false`.', false, {
206
- id: 'ember-data:deprecate-non-strict-relationships',
207
- for: 'ember-data',
208
- until: '5.0',
209
- since: { enabled: '4.7', available: '4.7' },
210
- });
211
- } else {
212
- assert(`Expected hasMany options.async to be a boolean`, options && typeof options.async === 'boolean');
213
- }
214
- } else {
215
- assert(`Expected hasMany options.async to be a boolean`, options && typeof options.async === 'boolean');
216
- }
217
-
218
- if (DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE) {
219
- if (options.inverse !== null && (typeof options.inverse !== 'string' || options.inverse.length === 0)) {
220
- deprecate(
221
- 'hasMany(<type>, <options>) must specify options.inverse as either `null` or string type of the related resource.',
222
- false,
223
- {
224
- id: 'ember-data:deprecate-non-strict-relationships',
225
- for: 'ember-data',
226
- until: '5.0',
227
- since: { enabled: '4.7', available: '4.7' },
228
- }
229
- );
230
- }
231
- }
232
-
233
- // Metadata about relationships is stored on the meta of
234
- // the relationship. This is used for introspection and
235
- // serialization. Note that `key` is populated lazily
236
- // the first time the CP is called.
237
- let meta = {
238
- type: normalizeType(type),
239
- options,
240
- isRelationship: true,
241
- kind: 'hasMany',
242
- name: 'Has Many',
243
- key: null,
244
- };
245
-
246
- return computed({
247
- get(key) {
248
- if (DEBUG) {
249
- if (['currentState'].indexOf(key) !== -1) {
250
- throw new Error(
251
- `'${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()}`
252
- );
253
- }
254
- }
255
- if (this.isDestroying || this.isDestroyed) {
256
- return A();
257
- }
258
- return lookupLegacySupport(this).getHasMany(key);
259
- },
260
- set(key, records) {
261
- if (DEBUG) {
262
- if (['currentState'].indexOf(key) !== -1) {
263
- throw new Error(
264
- `'${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()}`
265
- );
266
- }
267
- }
268
- const support = lookupLegacySupport(this);
269
- const manyArray = support.getManyArray(key);
270
- assert(`You must pass an array of records to set a hasMany relationship`, Array.isArray(records));
271
- this.store._join(() => {
272
- manyArray.splice(0, manyArray.length, ...records);
273
- });
274
-
275
- return support.getHasMany(key);
276
- },
277
- }).meta(meta);
278
- }
279
-
280
- export default computedMacroWithOptionalParams(hasMany);
@@ -1,14 +0,0 @@
1
- export { default as attr } from './attr';
2
- export { default as belongsTo } from './belongs-to';
3
- export { default as hasMany } from './has-many';
4
- export { default as Model } from './model';
5
- export { default as Errors } from './errors';
6
-
7
- export { default as ManyArray } from './many-array';
8
- export { default as PromiseBelongsTo } from './promise-belongs-to';
9
- export { default as PromiseManyArray } from './promise-many-array';
10
- export { default as _modelForMixin } from './model-for-mixin';
11
-
12
- // // Used by tests
13
- export { default as diffArray } from './diff-array';
14
- export { LEGACY_SUPPORT } from './model';
@@ -1,395 +0,0 @@
1
- import { assert, deprecate } from '@ember/debug';
2
- import { DEBUG } from '@glimmer/env';
3
-
4
- import { resolve } from 'rsvp';
5
-
6
- import {
7
- DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE,
8
- DEPRECATE_RSVP_PROMISE,
9
- } from '@ember-data/private-build-infra/deprecations';
10
-
11
- import { iterateData, normalizeResponseHelper } from './legacy-data-utils';
12
-
13
- export function _findHasMany(adapter, store, identifier, link, relationship, options) {
14
- const record = store._instanceCache.getRecord(identifier);
15
- const snapshot = store._instanceCache.createSnapshot(identifier, options);
16
- let modelClass = store.modelFor(relationship.type);
17
- let useLink = !link || typeof link === 'string';
18
- let relatedLink = useLink ? link : link.href;
19
- let promise = adapter.findHasMany(store, snapshot, relatedLink, relationship);
20
- let label = `DS: Handle Adapter#findHasMany of '${identifier.type}' : '${relationship.type}'`;
21
-
22
- promise = guardDestroyedStore(promise, store, label);
23
- promise = promise.then(
24
- (adapterPayload) => {
25
- if (!_objectIsAlive(record)) {
26
- if (DEPRECATE_RSVP_PROMISE) {
27
- deprecate(
28
- `A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`,
29
- false,
30
- {
31
- id: 'ember-data:rsvp-unresolved-async',
32
- until: '5.0',
33
- for: '@ember-data/store',
34
- since: {
35
- available: '4.5',
36
- enabled: '4.5',
37
- },
38
- }
39
- );
40
- }
41
- }
42
-
43
- assert(
44
- `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`,
45
- payloadIsNotBlank(adapterPayload)
46
- );
47
- let serializer = store.serializerFor(relationship.type);
48
- let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findHasMany');
49
-
50
- assert(
51
- `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: [] }`,
52
- 'data' in payload && Array.isArray(payload.data)
53
- );
54
-
55
- payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
56
-
57
- return store._push(payload);
58
- },
59
- null,
60
- `DS: Extract payload of '${identifier.type}' : hasMany '${relationship.type}'`
61
- );
62
-
63
- if (DEPRECATE_RSVP_PROMISE) {
64
- promise = _guard(promise, _bind(_objectIsAlive, record));
65
- }
66
-
67
- return promise;
68
- }
69
-
70
- export function _findBelongsTo(store, identifier, link, relationship, options) {
71
- const record = store._instanceCache.getRecord(identifier);
72
- let adapter = store.adapterFor(identifier.type);
73
-
74
- assert(`You tried to load a belongsTo relationship but you have no adapter (for ${identifier.type})`, adapter);
75
- assert(
76
- `You tried to load a belongsTo relationship from a specified 'link' in the original payload but your adapter does not implement 'findBelongsTo'`,
77
- typeof adapter.findBelongsTo === 'function'
78
- );
79
- let snapshot = store._instanceCache.createSnapshot(identifier, options);
80
- let modelClass = store.modelFor(relationship.type);
81
- let useLink = !link || typeof link === 'string';
82
- let relatedLink = useLink ? link : link.href;
83
- let promise = adapter.findBelongsTo(store, snapshot, relatedLink, relationship);
84
- let label = `DS: Handle Adapter#findBelongsTo of ${identifier.type} : ${relationship.type}`;
85
-
86
- promise = guardDestroyedStore(promise, store, label);
87
- promise = _guard(promise, _bind(_objectIsAlive, record));
88
-
89
- promise = promise.then(
90
- (adapterPayload) => {
91
- if (!_objectIsAlive(record)) {
92
- if (DEPRECATE_RSVP_PROMISE) {
93
- deprecate(
94
- `A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`,
95
- false,
96
- {
97
- id: 'ember-data:rsvp-unresolved-async',
98
- until: '5.0',
99
- for: '@ember-data/store',
100
- since: {
101
- available: '4.5',
102
- enabled: '4.5',
103
- },
104
- }
105
- );
106
- }
107
- }
108
-
109
- let serializer = store.serializerFor(relationship.type);
110
- let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo');
111
-
112
- assert(
113
- `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 }`,
114
- 'data' in payload &&
115
- (payload.data === null || (typeof payload.data === 'object' && !Array.isArray(payload.data)))
116
- );
117
-
118
- if (!payload.data && !payload.links && !payload.meta) {
119
- return null;
120
- }
121
-
122
- payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
123
-
124
- return store._push(payload);
125
- },
126
- null,
127
- `DS: Extract payload of ${identifier.type} : ${relationship.type}`
128
- );
129
-
130
- if (DEPRECATE_RSVP_PROMISE) {
131
- promise = _guard(promise, _bind(_objectIsAlive, record));
132
- }
133
-
134
- return promise;
135
- }
136
-
137
- // sync
138
- // iterate over records in payload.data
139
- // for each record
140
- // assert that record.relationships[inverse] is either undefined (so we can fix it)
141
- // or provide a data: {id, type} that matches the record that requested it
142
- // return the relationship data for the parent
143
- function syncRelationshipDataFromLink(store, payload, parentIdentifier, relationship) {
144
- // ensure the right hand side (incoming payload) points to the parent record that
145
- // requested this relationship
146
- let relationshipData = payload.data
147
- ? iterateData(payload.data, (data, index) => {
148
- const { id, type } = data;
149
- ensureRelationshipIsSetToParent(data, parentIdentifier, store, relationship, index);
150
- return { id, type };
151
- })
152
- : null;
153
-
154
- const relatedDataHash = {};
155
-
156
- if ('meta' in payload) {
157
- relatedDataHash.meta = payload.meta;
158
- }
159
- if ('links' in payload) {
160
- relatedDataHash.links = payload.links;
161
- }
162
- if ('data' in payload) {
163
- relatedDataHash.data = relationshipData;
164
- }
165
-
166
- // now, push the left hand side (the parent record) to ensure things are in sync, since
167
- // the payload will be pushed with store._push
168
- const parentPayload = {
169
- id: parentIdentifier.id,
170
- type: parentIdentifier.type,
171
- relationships: {
172
- [relationship.key]: relatedDataHash,
173
- },
174
- };
175
-
176
- if (!Array.isArray(payload.included)) {
177
- payload.included = [];
178
- }
179
- payload.included.push(parentPayload);
180
-
181
- return payload;
182
- }
183
-
184
- function ensureRelationshipIsSetToParent(payload, parentIdentifier, store, parentRelationship, index) {
185
- let { id, type } = payload;
186
-
187
- if (!payload.relationships) {
188
- payload.relationships = {};
189
- }
190
- let { relationships } = payload;
191
-
192
- let inverse = getInverse(store, parentIdentifier, parentRelationship, type);
193
- if (inverse) {
194
- let { inverseKey, kind } = inverse;
195
-
196
- let relationshipData = relationships[inverseKey] && relationships[inverseKey].data;
197
-
198
- if (DEBUG) {
199
- if (
200
- typeof relationshipData !== 'undefined' &&
201
- !relationshipDataPointsToParent(relationshipData, parentIdentifier)
202
- ) {
203
- let inspect = function inspect(thing) {
204
- return `'${JSON.stringify(thing)}'`;
205
- };
206
- let quotedType = inspect(type);
207
- let quotedInverse = inspect(inverseKey);
208
- let expected = inspect({
209
- id: parentIdentifier.id,
210
- type: parentIdentifier.type,
211
- });
212
- let expectedModel = `${parentIdentifier.type}:${parentIdentifier.id}`;
213
- let got = inspect(relationshipData);
214
- let prefix = typeof index === 'number' ? `data[${index}]` : `data`;
215
- let path = `${prefix}.relationships.${inverseKey}.data`;
216
- let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null;
217
- let relationshipFetched = `${expectedModel}.${parentRelationship.kind}("${parentRelationship.name}")`;
218
- let includedRecord = `<${type}:${id}>`;
219
- let message = [
220
- `Encountered mismatched relationship: Ember Data expected ${path} in the payload from ${relationshipFetched} to include ${expected} but got ${got} instead.\n`,
221
- `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.`,
222
- `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.`,
223
- `Ember Data has corrected the ${includedRecord} record's ${quotedInverse} relationship to ${expectedModel} so that ${relationshipFetched} will include ${includedRecord}.`,
224
- `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.`,
225
- ].join('\n');
226
-
227
- assert(message);
228
- }
229
- }
230
-
231
- if (kind !== 'hasMany' || typeof relationshipData !== 'undefined') {
232
- relationships[inverseKey] = relationships[inverseKey] || {};
233
- relationships[inverseKey].data = fixRelationshipData(relationshipData, kind, parentIdentifier);
234
- }
235
- }
236
- }
237
-
238
- function metaIsRelationshipDefinition(meta) {
239
- return typeof meta._inverseKey === 'function';
240
- }
241
-
242
- function inverseForRelationship(store, identifier, key) {
243
- const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor(identifier)[key];
244
- if (!definition) {
245
- return null;
246
- }
247
-
248
- if (DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE) {
249
- if (metaIsRelationshipDefinition(definition)) {
250
- const modelClass = store.modelFor(identifier.type);
251
- return definition._inverseKey(store, modelClass);
252
- }
253
- }
254
- assert(
255
- `Expected the relationship defintion to specify the inverse type or null.`,
256
- definition.options?.inverse === null ||
257
- (typeof definition.options?.inverse === 'string' && definition.options.inverse.length > 0)
258
- );
259
- return definition.options.inverse;
260
- }
261
-
262
- function getInverse(store, parentIdentifier, parentRelationship, type) {
263
- let { name: lhs_relationshipName } = parentRelationship;
264
- let { type: parentType } = parentIdentifier;
265
- let inverseKey = inverseForRelationship(store, { type: parentType }, lhs_relationshipName);
266
-
267
- if (inverseKey) {
268
- const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor({ type });
269
- let { kind } = definition[inverseKey];
270
- return {
271
- inverseKey,
272
- kind,
273
- };
274
- }
275
- }
276
-
277
- function relationshipDataPointsToParent(relationshipData, identifier) {
278
- if (relationshipData === null) {
279
- return false;
280
- }
281
-
282
- if (Array.isArray(relationshipData)) {
283
- if (relationshipData.length === 0) {
284
- return false;
285
- }
286
- for (let i = 0; i < relationshipData.length; i++) {
287
- let entry = relationshipData[i];
288
- if (validateRelationshipEntry(entry, identifier)) {
289
- return true;
290
- }
291
- }
292
- } else {
293
- return validateRelationshipEntry(relationshipData, identifier);
294
- }
295
-
296
- return false;
297
- }
298
-
299
- function fixRelationshipData(relationshipData, relationshipKind, { id, type }) {
300
- let parentRelationshipData = {
301
- id,
302
- type,
303
- };
304
-
305
- let payload;
306
-
307
- if (relationshipKind === 'hasMany') {
308
- payload = relationshipData || [];
309
- if (relationshipData) {
310
- // these arrays could be massive so this is better than filter
311
- // Note: this is potentially problematic if type/id are not in the
312
- // same state of normalization.
313
- let found = relationshipData.find((v) => {
314
- return v.type === parentRelationshipData.type && v.id === parentRelationshipData.id;
315
- });
316
- if (!found) {
317
- payload.push(parentRelationshipData);
318
- }
319
- } else {
320
- payload.push(parentRelationshipData);
321
- }
322
- } else {
323
- payload = relationshipData || {};
324
- Object.assign(payload, parentRelationshipData);
325
- }
326
-
327
- return payload;
328
- }
329
-
330
- function validateRelationshipEntry({ id }, { id: parentModelID }) {
331
- return id && id.toString() === parentModelID;
332
- }
333
-
334
- function _bind(fn, ...args) {
335
- return function () {
336
- return fn.apply(undefined, args);
337
- };
338
- }
339
-
340
- function _guard(promise, test) {
341
- let guarded = promise.finally(() => {
342
- if (!test()) {
343
- guarded._subscribers.length = 0;
344
- }
345
- });
346
-
347
- return guarded;
348
- }
349
-
350
- function _objectIsAlive(object) {
351
- return !(object.isDestroyed || object.isDestroying);
352
- }
353
-
354
- function payloadIsNotBlank(adapterPayload) {
355
- if (Array.isArray(adapterPayload)) {
356
- return true;
357
- } else {
358
- return Object.keys(adapterPayload || {}).length;
359
- }
360
- }
361
-
362
- function guardDestroyedStore(promise, store, label) {
363
- let token;
364
- if (DEBUG) {
365
- token = store._trackAsyncRequestStart(label);
366
- }
367
- let wrapperPromise = resolve(promise, label).then((_v) => {
368
- if (!_objectIsAlive(store)) {
369
- if (DEPRECATE_RSVP_PROMISE) {
370
- deprecate(
371
- `A Promise did not resolve by the time the store was destroyed. This will error in a future release.`,
372
- false,
373
- {
374
- id: 'ember-data:rsvp-unresolved-async',
375
- until: '5.0',
376
- for: '@ember-data/store',
377
- since: {
378
- available: '4.5',
379
- enabled: '4.5',
380
- },
381
- }
382
- );
383
- }
384
- }
385
-
386
- return promise;
387
- });
388
-
389
- return _guard(wrapperPromise, () => {
390
- if (DEBUG) {
391
- store._trackAsyncRequestEnd(token);
392
- }
393
- return _objectIsAlive(store);
394
- });
395
- }