@ember-data/model 4.8.0-alpha.6 → 4.9.0-alpha.1
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.
|
@@ -150,10 +150,11 @@ export class LegacySupport {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
let promise = this._findBelongsTo(key, resource, relationship, options);
|
|
153
|
+
const isLoaded = relatedIdentifier && store._instanceCache.recordIsLoaded(relatedIdentifier);
|
|
153
154
|
|
|
154
155
|
return this._updatePromiseProxyFor('belongsTo', key, {
|
|
155
156
|
promise,
|
|
156
|
-
content:
|
|
157
|
+
content: isLoaded ? store._instanceCache.getRecord(relatedIdentifier!) : null,
|
|
157
158
|
_belongsToState,
|
|
158
159
|
});
|
|
159
160
|
} else {
|
|
@@ -210,38 +211,40 @@ export class LegacySupport {
|
|
|
210
211
|
}
|
|
211
212
|
|
|
212
213
|
getManyArray(key: string, definition?: UpgradedMeta): RelatedCollection {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
214
|
+
if (HAS_RECORD_DATA_PACKAGE) {
|
|
215
|
+
let manyArray: RelatedCollection | undefined = this._manyArrayCache[key];
|
|
216
|
+
if (!definition) {
|
|
217
|
+
const graphFor = (
|
|
218
|
+
importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
|
|
219
|
+
).graphFor;
|
|
220
|
+
definition = graphFor(this.store).get(this.identifier, key).definition;
|
|
221
|
+
}
|
|
221
222
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
223
|
+
if (!manyArray) {
|
|
224
|
+
const [identifiers, doc] = this._getCurrentState(this.identifier, key);
|
|
225
|
+
|
|
226
|
+
manyArray = new RelatedCollection({
|
|
227
|
+
store: this.store,
|
|
228
|
+
type: definition.type,
|
|
229
|
+
identifier: this.identifier,
|
|
230
|
+
recordData: this.recordData,
|
|
231
|
+
identifiers,
|
|
232
|
+
key,
|
|
233
|
+
meta: doc.meta || null,
|
|
234
|
+
links: doc.links || null,
|
|
235
|
+
isPolymorphic: definition.isPolymorphic,
|
|
236
|
+
isAsync: definition.isAsync,
|
|
237
|
+
_inverseIsAsync: definition.inverseIsAsync,
|
|
238
|
+
manager: this,
|
|
239
|
+
isLoaded: !definition.isAsync,
|
|
240
|
+
allowMutation: true,
|
|
241
|
+
});
|
|
242
|
+
this._manyArrayCache[key] = manyArray;
|
|
243
|
+
}
|
|
243
244
|
|
|
244
|
-
|
|
245
|
+
return manyArray;
|
|
246
|
+
}
|
|
247
|
+
assert('hasMany only works with the @ember-data/record-data package');
|
|
245
248
|
}
|
|
246
249
|
|
|
247
250
|
fetchAsyncHasMany(
|
package/addon/-private/model.js
CHANGED
|
@@ -7,7 +7,6 @@ import EmberError from '@ember/error';
|
|
|
7
7
|
import EmberObject from '@ember/object';
|
|
8
8
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
9
9
|
import { run } from '@ember/runloop';
|
|
10
|
-
import { isNone } from '@ember/utils';
|
|
11
10
|
import { DEBUG } from '@glimmer/env';
|
|
12
11
|
import { tracked } from '@glimmer/tracking';
|
|
13
12
|
import Ember from 'ember';
|
|
@@ -18,6 +17,7 @@ import { HAS_DEBUG_PACKAGE } from '@ember-data/private-build-infra';
|
|
|
18
17
|
import {
|
|
19
18
|
DEPRECATE_EARLY_STATIC,
|
|
20
19
|
DEPRECATE_MODEL_REOPEN,
|
|
20
|
+
DEPRECATE_NON_EXPLICIT_POLYMORPHISM,
|
|
21
21
|
DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE,
|
|
22
22
|
DEPRECATE_SAVE_PROMISE_ACCESS,
|
|
23
23
|
} from '@ember-data/private-build-infra/deprecations';
|
|
@@ -58,7 +58,7 @@ function findPossibleInverses(type, inverseType, name, relationshipsSoFar) {
|
|
|
58
58
|
let relationshipsForType = relationshipMap.get(type.modelName);
|
|
59
59
|
let relationships = Array.isArray(relationshipsForType)
|
|
60
60
|
? relationshipsForType.filter((relationship) => {
|
|
61
|
-
let optionsForRelationship =
|
|
61
|
+
let optionsForRelationship = relationship.options;
|
|
62
62
|
|
|
63
63
|
if (!optionsForRelationship.inverse && optionsForRelationship.inverse !== null) {
|
|
64
64
|
return true;
|
|
@@ -1394,42 +1394,46 @@ class Model extends EmberObject {
|
|
|
1394
1394
|
this.modelName
|
|
1395
1395
|
);
|
|
1396
1396
|
}
|
|
1397
|
-
let inverseType = this.typeForRelationship(name, store);
|
|
1398
|
-
if (!inverseType) {
|
|
1399
|
-
return null;
|
|
1400
|
-
}
|
|
1401
1397
|
|
|
1402
|
-
|
|
1398
|
+
const relationship = this.relationshipsByName.get(name);
|
|
1399
|
+
const { options } = relationship;
|
|
1400
|
+
const isPolymorphic = options.polymorphic;
|
|
1401
|
+
|
|
1403
1402
|
//If inverse is manually specified to be null, like `comments: hasMany('message', { inverse: null })`
|
|
1404
|
-
|
|
1405
|
-
|
|
1403
|
+
const isExplicitInverseNull = options.inverse === null;
|
|
1404
|
+
const isAbstractType =
|
|
1405
|
+
!isExplicitInverseNull && isPolymorphic && !store.getSchemaDefinitionService().doesTypeExist(relationship.type);
|
|
1406
|
+
|
|
1407
|
+
if (isExplicitInverseNull || isAbstractType) {
|
|
1408
|
+
assert(
|
|
1409
|
+
`No schema for the abstract type '${relationship.type}' for the polymorphic relationship '${name}' on '${this.modelName}' was provided by the SchemaDefinitionService.`,
|
|
1410
|
+
!isPolymorphic || isExplicitInverseNull
|
|
1411
|
+
);
|
|
1406
1412
|
return null;
|
|
1407
1413
|
}
|
|
1408
1414
|
|
|
1409
|
-
let
|
|
1415
|
+
let fieldOnInverse, inverseKind, inverseRelationship, inverseOptions;
|
|
1416
|
+
let inverseSchema = this.typeForRelationship(name, store);
|
|
1410
1417
|
|
|
1418
|
+
// if the type does not exist and we are not polymorphic
|
|
1411
1419
|
//If inverse is specified manually, return the inverse
|
|
1412
|
-
if (options.inverse) {
|
|
1413
|
-
|
|
1414
|
-
|
|
1420
|
+
if (options.inverse !== undefined) {
|
|
1421
|
+
fieldOnInverse = options.inverse;
|
|
1422
|
+
inverseRelationship = inverseSchema && inverseSchema.relationshipsByName.get(fieldOnInverse);
|
|
1415
1423
|
|
|
1416
1424
|
assert(
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
"' on the '" +
|
|
1420
|
-
inverseType.modelName +
|
|
1421
|
-
"' model. This is most likely due to a missing attribute on your model definition.",
|
|
1422
|
-
!isNone(inverse)
|
|
1425
|
+
`We found no field named '${fieldOnInverse}' on the schema for '${inverseSchema.modelName}' to be the inverse of the '${name}' relationship on '${this.modelName}'. This is most likely due to a missing field on your model definition.`,
|
|
1426
|
+
inverseRelationship
|
|
1423
1427
|
);
|
|
1424
1428
|
|
|
1425
1429
|
// TODO probably just return the whole inverse here
|
|
1426
|
-
inverseKind =
|
|
1427
|
-
inverseOptions =
|
|
1430
|
+
inverseKind = inverseRelationship.kind;
|
|
1431
|
+
inverseOptions = inverseRelationship.options;
|
|
1428
1432
|
} else {
|
|
1429
1433
|
//No inverse was specified manually, we need to use a heuristic to guess one
|
|
1430
|
-
if (
|
|
1434
|
+
if (relationship.type === relationship.parentModelName) {
|
|
1431
1435
|
warn(
|
|
1432
|
-
`Detected a reflexive relationship
|
|
1436
|
+
`Detected a reflexive relationship named '${name}' on the schema for '${relationship.type}' without an inverse option. Look at https://guides.emberjs.com/current/models/relationships/#toc_reflexive-relations for how to explicitly specify inverses.`,
|
|
1433
1437
|
false,
|
|
1434
1438
|
{
|
|
1435
1439
|
id: 'ds.model.reflexive-relationship-without-inverse',
|
|
@@ -1437,30 +1441,33 @@ class Model extends EmberObject {
|
|
|
1437
1441
|
);
|
|
1438
1442
|
}
|
|
1439
1443
|
|
|
1440
|
-
let possibleRelationships = findPossibleInverses(this,
|
|
1444
|
+
let possibleRelationships = findPossibleInverses(this, inverseSchema, name);
|
|
1441
1445
|
|
|
1442
1446
|
if (possibleRelationships.length === 0) {
|
|
1443
1447
|
return null;
|
|
1444
1448
|
}
|
|
1445
1449
|
|
|
1446
|
-
|
|
1447
|
-
let
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
+
if (DEBUG) {
|
|
1451
|
+
let filteredRelationships = possibleRelationships.filter((possibleRelationship) => {
|
|
1452
|
+
let optionsForRelationship = possibleRelationship.options;
|
|
1453
|
+
return name === optionsForRelationship.inverse;
|
|
1454
|
+
});
|
|
1450
1455
|
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1456
|
+
assert(
|
|
1457
|
+
"You defined the '" +
|
|
1458
|
+
name +
|
|
1459
|
+
"' relationship on " +
|
|
1460
|
+
this +
|
|
1461
|
+
', but you defined the inverse relationships of type ' +
|
|
1462
|
+
inverseSchema.toString() +
|
|
1463
|
+
' multiple times. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses',
|
|
1464
|
+
filteredRelationships.length < 2
|
|
1465
|
+
);
|
|
1466
|
+
}
|
|
1461
1467
|
|
|
1462
|
-
|
|
1463
|
-
|
|
1468
|
+
let explicitRelationship = possibleRelationships.find((relationship) => relationship.options.inverse === name);
|
|
1469
|
+
if (explicitRelationship) {
|
|
1470
|
+
possibleRelationships = [explicitRelationship];
|
|
1464
1471
|
}
|
|
1465
1472
|
|
|
1466
1473
|
assert(
|
|
@@ -1471,24 +1478,78 @@ class Model extends EmberObject {
|
|
|
1471
1478
|
', but multiple possible inverse relationships of type ' +
|
|
1472
1479
|
this +
|
|
1473
1480
|
' were found on ' +
|
|
1474
|
-
|
|
1481
|
+
inverseSchema +
|
|
1475
1482
|
'. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses',
|
|
1476
1483
|
possibleRelationships.length === 1
|
|
1477
1484
|
);
|
|
1478
1485
|
|
|
1479
|
-
|
|
1486
|
+
fieldOnInverse = possibleRelationships[0].name;
|
|
1480
1487
|
inverseKind = possibleRelationships[0].kind;
|
|
1481
1488
|
inverseOptions = possibleRelationships[0].options;
|
|
1482
1489
|
}
|
|
1483
1490
|
|
|
1491
|
+
// ensure inverse is properly configured
|
|
1492
|
+
if (DEBUG && isPolymorphic) {
|
|
1493
|
+
if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM) {
|
|
1494
|
+
if (!inverseOptions.as) {
|
|
1495
|
+
deprecate(
|
|
1496
|
+
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${fieldOnInverse}' on type '${inverseSchema.modelName}' is misconfigured.`,
|
|
1497
|
+
false,
|
|
1498
|
+
{
|
|
1499
|
+
id: 'ember-data:non-explicit-relationships',
|
|
1500
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
1501
|
+
until: '5.0',
|
|
1502
|
+
for: 'ember-data',
|
|
1503
|
+
}
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
} else {
|
|
1507
|
+
assert(
|
|
1508
|
+
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${fieldOnInverse}' on type '${inverseSchema.modelName}' is misconfigured.`,
|
|
1509
|
+
inverseOptions.as
|
|
1510
|
+
);
|
|
1511
|
+
assert(
|
|
1512
|
+
`options.as should match the expected type of the polymorphic relationship. Expected field '${fieldOnInverse}' on type '${inverseSchema.modelName}' to specify '${relationship.type}' but found '${inverseOptions.as}'`,
|
|
1513
|
+
!!inverseOptions.as && relationship.type === inverseOptions.as
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
// ensure we are properly configured
|
|
1519
|
+
if (DEBUG && inverseOptions.polymorphic) {
|
|
1520
|
+
if (DEPRECATE_NON_EXPLICIT_POLYMORPHISM) {
|
|
1521
|
+
if (!options.as) {
|
|
1522
|
+
deprecate(
|
|
1523
|
+
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${name}' on type '${this.modelName}' is misconfigured.`,
|
|
1524
|
+
false,
|
|
1525
|
+
{
|
|
1526
|
+
id: 'ember-data:non-explicit-relationships',
|
|
1527
|
+
since: { enabled: '4.8', available: '4.8' },
|
|
1528
|
+
until: '5.0',
|
|
1529
|
+
for: 'ember-data',
|
|
1530
|
+
}
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
} else {
|
|
1534
|
+
assert(
|
|
1535
|
+
`Relationships that satisfy polymorphic relationships MUST define which abstract-type they are satisfying using 'as'. The field '${name}' on type '${this.modelName}' is misconfigured.`,
|
|
1536
|
+
options.as
|
|
1537
|
+
);
|
|
1538
|
+
assert(
|
|
1539
|
+
`options.as should match the expected type of the polymorphic relationship. Expected field '${name}' on type '${this.modelName}' to specify '${inverseRelationship.type}' but found '${options.as}'`,
|
|
1540
|
+
!!options.as && inverseRelationship.type === options.as
|
|
1541
|
+
);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1484
1545
|
assert(
|
|
1485
|
-
`The ${
|
|
1486
|
-
|
|
1546
|
+
`The ${inverseSchema.modelName}:${fieldOnInverse} relationship declares 'inverse: null', but it was resolved as the inverse for ${this.modelName}:${name}.`,
|
|
1547
|
+
inverseOptions.inverse !== null
|
|
1487
1548
|
);
|
|
1488
1549
|
|
|
1489
1550
|
return {
|
|
1490
|
-
type:
|
|
1491
|
-
name:
|
|
1551
|
+
type: inverseSchema,
|
|
1552
|
+
name: fieldOnInverse,
|
|
1492
1553
|
kind: inverseKind,
|
|
1493
1554
|
options: inverseOptions,
|
|
1494
1555
|
};
|
|
@@ -6,7 +6,7 @@ import type { Object as JSONObject, Value as JSONValue } from 'json-typescript';
|
|
|
6
6
|
import { resolve } from 'rsvp';
|
|
7
7
|
|
|
8
8
|
import { DEPRECATE_PROMISE_PROXIES } from '@ember-data/private-build-infra/deprecations';
|
|
9
|
-
import type { Graph } from '@ember-data/record-data/-private/graph';
|
|
9
|
+
import type { Graph } from '@ember-data/record-data/-private/graph/graph';
|
|
10
10
|
import type BelongsToRelationship from '@ember-data/record-data/-private/relationships/state/belongs-to';
|
|
11
11
|
import type Store from '@ember-data/store';
|
|
12
12
|
import { assertPolymorphicType } from '@ember-data/store/-debug';
|
|
@@ -9,7 +9,7 @@ import { resolve } from 'rsvp';
|
|
|
9
9
|
import { ManyArray } from 'ember-data/-private';
|
|
10
10
|
|
|
11
11
|
import { DEPRECATE_PROMISE_PROXIES } from '@ember-data/private-build-infra/deprecations';
|
|
12
|
-
import type { Graph } from '@ember-data/record-data/-private/graph';
|
|
12
|
+
import type { Graph } from '@ember-data/record-data/-private/graph/graph';
|
|
13
13
|
import type ManyRelationship from '@ember-data/record-data/-private/relationships/state/has-many';
|
|
14
14
|
import type Store from '@ember-data/store';
|
|
15
15
|
import { recordIdentifierFor } from '@ember-data/store';
|
|
@@ -75,7 +75,9 @@ class RelationshipDefinition implements RelationshipSchema {
|
|
|
75
75
|
|
|
76
76
|
if (shouldFindInverse(this.meta)) {
|
|
77
77
|
inverse = modelClass.inverseFor(this.key, store);
|
|
78
|
-
}
|
|
78
|
+
}
|
|
79
|
+
// TODO make this error again for the non-polymorphic case
|
|
80
|
+
if (DEBUG && !this.options.polymorphic) {
|
|
79
81
|
modelClass.typeForRelationship(this.key, store);
|
|
80
82
|
}
|
|
81
83
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ember-data/model",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.0-alpha.1",
|
|
4
4
|
"description": "A presentation layer for apps built with @ember-data/store",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"test:node": "mocha"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@ember-data/canary-features": "4.
|
|
26
|
-
"@ember-data/private-build-infra": "4.
|
|
27
|
-
"@ember-data/store": "4.
|
|
25
|
+
"@ember-data/canary-features": "4.9.0-alpha.1",
|
|
26
|
+
"@ember-data/private-build-infra": "4.9.0-alpha.1",
|
|
27
|
+
"@ember-data/store": "4.9.0-alpha.1",
|
|
28
28
|
"@ember/edition-utils": "^1.2.0",
|
|
29
29
|
"@ember/string": "^3.0.0",
|
|
30
30
|
"@embroider/macros": "^1.8.3",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"inflection": "~1.13.2"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@ember-data/unpublished-test-infra": "4.
|
|
41
|
+
"@ember-data/unpublished-test-infra": "4.9.0-alpha.1",
|
|
42
42
|
"@ember/optional-features": "^2.0.0",
|
|
43
43
|
"@ember/test-helpers": "~2.7.0",
|
|
44
44
|
"broccoli-asset-rev": "^3.0.0",
|