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