@ember-data/model 4.8.0-alpha.3 → 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/attr.js +5 -31
- package/addon/-private/belongs-to.js +78 -22
- package/addon/-private/deprecated-promise-proxy.ts +54 -0
- package/addon/-private/has-many.js +77 -19
- package/addon/-private/legacy-data-fetch.js +28 -8
- package/addon/-private/legacy-relationships-support.ts +247 -180
- package/addon/-private/many-array.ts +213 -245
- package/addon/-private/model.js +53 -38
- package/addon/-private/notify-changes.ts +1 -1
- 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/record-state.ts +7 -13
- package/addon/-private/references/belongs-to.ts +62 -35
- package/addon/-private/references/has-many.ts +82 -49
- package/addon/-private/relationship-meta.ts +3 -23
- package/index.js +2 -0
- package/package.json +12 -8
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { deprecate } from '@ember/debug';
|
|
1
2
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
2
3
|
import { DEBUG } from '@glimmer/env';
|
|
3
4
|
import { cached, tracked } from '@glimmer/tracking';
|
|
@@ -7,12 +8,13 @@ import { resolve } from 'rsvp';
|
|
|
7
8
|
|
|
8
9
|
import { ManyArray } from 'ember-data/-private';
|
|
9
10
|
|
|
10
|
-
import
|
|
11
|
+
import { DEPRECATE_PROMISE_PROXIES } from '@ember-data/private-build-infra/deprecations';
|
|
12
|
+
import type { Graph } from '@ember-data/record-data/-private/graph';
|
|
13
|
+
import type ManyRelationship from '@ember-data/record-data/-private/relationships/state/has-many';
|
|
11
14
|
import type Store from '@ember-data/store';
|
|
12
15
|
import { recordIdentifierFor } from '@ember-data/store';
|
|
13
16
|
import { assertPolymorphicType } from '@ember-data/store/-debug';
|
|
14
17
|
import type { NotificationType } from '@ember-data/store/-private/managers/record-notification-manager';
|
|
15
|
-
import type { DebugWeakCache } from '@ember-data/store/-private/utils/weak-cache';
|
|
16
18
|
import type {
|
|
17
19
|
CollectionResourceDocument,
|
|
18
20
|
CollectionResourceRelationship,
|
|
@@ -53,48 +55,51 @@ function isResourceIdentiferWithRelatedLinks(
|
|
|
53
55
|
@extends Reference
|
|
54
56
|
*/
|
|
55
57
|
export default class HasManyReference {
|
|
58
|
+
declare graph: Graph;
|
|
56
59
|
declare key: string;
|
|
57
60
|
declare hasManyRelationship: ManyRelationship;
|
|
58
61
|
declare type: string;
|
|
59
62
|
declare store: Store;
|
|
60
63
|
|
|
61
64
|
// unsubscribe tokens given to us by the notification manager
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
___token!: Object;
|
|
66
|
+
___identifier: StableRecordIdentifier;
|
|
67
|
+
___relatedTokenMap!: Map<StableRecordIdentifier, Object>;
|
|
65
68
|
|
|
66
69
|
@tracked _ref = 0;
|
|
67
70
|
|
|
68
71
|
constructor(
|
|
69
72
|
store: Store,
|
|
73
|
+
graph: Graph,
|
|
70
74
|
parentIdentifier: StableRecordIdentifier,
|
|
71
75
|
hasManyRelationship: ManyRelationship,
|
|
72
76
|
key: string
|
|
73
77
|
) {
|
|
78
|
+
this.graph = graph;
|
|
74
79
|
this.key = key;
|
|
75
80
|
this.hasManyRelationship = hasManyRelationship;
|
|
76
81
|
this.type = hasManyRelationship.definition.type;
|
|
77
82
|
|
|
78
83
|
this.store = store;
|
|
79
|
-
this
|
|
80
|
-
this
|
|
84
|
+
this.___identifier = parentIdentifier;
|
|
85
|
+
this.___token = store._notificationManager.subscribe(
|
|
81
86
|
parentIdentifier,
|
|
82
87
|
(_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
|
|
83
|
-
if (
|
|
88
|
+
if (bucket === 'relationships' && notifiedKey === key) {
|
|
84
89
|
this._ref++;
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
92
|
);
|
|
88
|
-
this
|
|
93
|
+
this.___relatedTokenMap = new Map();
|
|
89
94
|
// TODO inverse
|
|
90
95
|
}
|
|
91
96
|
|
|
92
97
|
destroy() {
|
|
93
|
-
this.store._notificationManager.unsubscribe(this
|
|
94
|
-
this
|
|
98
|
+
this.store._notificationManager.unsubscribe(this.___token);
|
|
99
|
+
this.___relatedTokenMap.forEach((token) => {
|
|
95
100
|
this.store._notificationManager.unsubscribe(token);
|
|
96
101
|
});
|
|
97
|
-
this
|
|
102
|
+
this.___relatedTokenMap.clear();
|
|
98
103
|
}
|
|
99
104
|
|
|
100
105
|
@cached
|
|
@@ -104,34 +109,44 @@ export default class HasManyReference {
|
|
|
104
109
|
|
|
105
110
|
let resource = this._resource();
|
|
106
111
|
|
|
107
|
-
this
|
|
108
|
-
|
|
109
|
-
});
|
|
110
|
-
this.#relatedTokenMap.clear();
|
|
112
|
+
let map = this.___relatedTokenMap;
|
|
113
|
+
this.___relatedTokenMap = new Map();
|
|
111
114
|
|
|
112
115
|
if (resource && resource.data) {
|
|
113
116
|
return resource.data.map((resourceIdentifier) => {
|
|
114
117
|
const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
let token = map.get(identifier);
|
|
119
|
+
|
|
120
|
+
if (token) {
|
|
121
|
+
map.delete(identifier);
|
|
122
|
+
} else {
|
|
123
|
+
token = this.store._notificationManager.subscribe(
|
|
124
|
+
identifier,
|
|
125
|
+
(_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
|
|
126
|
+
if (bucket === 'identity' || (bucket === 'attributes' && notifiedKey === 'id')) {
|
|
127
|
+
this._ref++;
|
|
128
|
+
}
|
|
120
129
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
this.#relatedTokenMap.set(identifier, token);
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
this.___relatedTokenMap.set(identifier, token);
|
|
125
133
|
|
|
126
134
|
return identifier;
|
|
127
135
|
});
|
|
128
136
|
}
|
|
129
137
|
|
|
138
|
+
map.forEach((token) => {
|
|
139
|
+
this.store._notificationManager.unsubscribe(token);
|
|
140
|
+
});
|
|
141
|
+
map.clear();
|
|
142
|
+
|
|
130
143
|
return [];
|
|
131
144
|
}
|
|
132
145
|
|
|
133
146
|
_resource() {
|
|
134
|
-
return this.store._instanceCache
|
|
147
|
+
return this.store._instanceCache
|
|
148
|
+
.getRecordData(this.___identifier)
|
|
149
|
+
.getRelationship(this.___identifier, this.key) as CollectionResourceRelationship;
|
|
135
150
|
}
|
|
136
151
|
|
|
137
152
|
/**
|
|
@@ -145,7 +160,7 @@ export default class HasManyReference {
|
|
|
145
160
|
import Model, { hasMany } from '@ember-data/model';
|
|
146
161
|
|
|
147
162
|
export default class PostModel extends Model {
|
|
148
|
-
@hasMany({ async: true }) comments;
|
|
163
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
149
164
|
}
|
|
150
165
|
```
|
|
151
166
|
|
|
@@ -194,7 +209,7 @@ export default class HasManyReference {
|
|
|
194
209
|
import Model, { hasMany } from '@ember-data/model';
|
|
195
210
|
|
|
196
211
|
export default class PostModel extends Model {
|
|
197
|
-
@hasMany({ async: true }) comments;
|
|
212
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
198
213
|
}
|
|
199
214
|
```
|
|
200
215
|
|
|
@@ -234,7 +249,7 @@ export default class HasManyReference {
|
|
|
234
249
|
// models/blog.js
|
|
235
250
|
import Model, { belongsTo } from '@ember-data/model';
|
|
236
251
|
export default Model.extend({
|
|
237
|
-
user: belongsTo({ async: true })
|
|
252
|
+
user: belongsTo('user', { async: true, inverse: null })
|
|
238
253
|
});
|
|
239
254
|
|
|
240
255
|
let blog = store.push({
|
|
@@ -296,7 +311,7 @@ export default class HasManyReference {
|
|
|
296
311
|
// models/blog.js
|
|
297
312
|
import Model, { hasMany } from '@ember-data/model';
|
|
298
313
|
export default Model.extend({
|
|
299
|
-
users: hasMany({ async: true })
|
|
314
|
+
users: hasMany('user', { async: true, inverse: null })
|
|
300
315
|
});
|
|
301
316
|
|
|
302
317
|
let blog = store.push({
|
|
@@ -347,7 +362,7 @@ export default class HasManyReference {
|
|
|
347
362
|
import Model, { hasMany } from '@ember-data/model';
|
|
348
363
|
|
|
349
364
|
export default class PostModel extends Model {
|
|
350
|
-
@hasMany({ async: true }) comments;
|
|
365
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
351
366
|
}
|
|
352
367
|
```
|
|
353
368
|
|
|
@@ -384,7 +399,25 @@ export default class HasManyReference {
|
|
|
384
399
|
async push(
|
|
385
400
|
objectOrPromise: ExistingResourceObject[] | CollectionResourceDocument | { data: SingleResourceDocument[] }
|
|
386
401
|
): Promise<ManyArray> {
|
|
387
|
-
|
|
402
|
+
let payload = objectOrPromise;
|
|
403
|
+
if (DEPRECATE_PROMISE_PROXIES && (objectOrPromise as unknown as { then: unknown }).then) {
|
|
404
|
+
payload = await resolve(objectOrPromise);
|
|
405
|
+
if (payload !== objectOrPromise) {
|
|
406
|
+
deprecate(
|
|
407
|
+
`You passed in a Promise to a Reference API that now expects a resolved value. await the value before setting it.`,
|
|
408
|
+
false,
|
|
409
|
+
{
|
|
410
|
+
id: 'ember-data:deprecate-promise-proxies',
|
|
411
|
+
until: '5.0',
|
|
412
|
+
since: {
|
|
413
|
+
enabled: '4.8',
|
|
414
|
+
available: '4.8',
|
|
415
|
+
},
|
|
416
|
+
for: 'ember-data',
|
|
417
|
+
}
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
388
421
|
let array: Array<ExistingResourceObject | SingleResourceDocument>;
|
|
389
422
|
|
|
390
423
|
if (!Array.isArray(payload) && typeof payload === 'object' && Array.isArray(payload.data)) {
|
|
@@ -414,9 +447,9 @@ export default class HasManyReference {
|
|
|
414
447
|
return recordIdentifierFor(record);
|
|
415
448
|
});
|
|
416
449
|
|
|
417
|
-
const {
|
|
418
|
-
store.
|
|
419
|
-
graph.push({
|
|
450
|
+
const { identifier } = this.hasManyRelationship;
|
|
451
|
+
store._join(() => {
|
|
452
|
+
this.graph.push({
|
|
420
453
|
op: 'replaceRelatedRecords',
|
|
421
454
|
record: identifier,
|
|
422
455
|
field: this.key,
|
|
@@ -433,9 +466,9 @@ export default class HasManyReference {
|
|
|
433
466
|
return false;
|
|
434
467
|
}
|
|
435
468
|
|
|
436
|
-
let
|
|
469
|
+
let localState = this.hasManyRelationship.localState;
|
|
437
470
|
|
|
438
|
-
return
|
|
471
|
+
return localState.every((identifier) => {
|
|
439
472
|
return this.store._instanceCache.recordIsLoaded(identifier, true) === true;
|
|
440
473
|
});
|
|
441
474
|
}
|
|
@@ -453,7 +486,7 @@ export default class HasManyReference {
|
|
|
453
486
|
import Model, { hasMany } from '@ember-data/model';
|
|
454
487
|
|
|
455
488
|
export default class PostModel extends Model {
|
|
456
|
-
@hasMany({ async: true }) comments;
|
|
489
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
457
490
|
}
|
|
458
491
|
```
|
|
459
492
|
|
|
@@ -482,9 +515,9 @@ export default class HasManyReference {
|
|
|
482
515
|
@return {ManyArray}
|
|
483
516
|
*/
|
|
484
517
|
value() {
|
|
485
|
-
const support: LegacySupport = (
|
|
486
|
-
|
|
487
|
-
)
|
|
518
|
+
const support: LegacySupport = (LEGACY_SUPPORT as Map<StableRecordIdentifier, LegacySupport>).get(
|
|
519
|
+
this.___identifier
|
|
520
|
+
)!;
|
|
488
521
|
|
|
489
522
|
return this._isLoaded() ? support.getManyArray(this.key) : null;
|
|
490
523
|
}
|
|
@@ -501,7 +534,7 @@ export default class HasManyReference {
|
|
|
501
534
|
import Model, { hasMany } from '@ember-data/model';
|
|
502
535
|
|
|
503
536
|
export default class PostModel extends Model {
|
|
504
|
-
@hasMany({ async: true }) comments;
|
|
537
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
505
538
|
}
|
|
506
539
|
```
|
|
507
540
|
|
|
@@ -554,9 +587,9 @@ export default class HasManyReference {
|
|
|
554
587
|
this has-many relationship.
|
|
555
588
|
*/
|
|
556
589
|
async load(options?: FindOptions): Promise<ManyArray> {
|
|
557
|
-
const support: LegacySupport = (
|
|
558
|
-
|
|
559
|
-
)
|
|
590
|
+
const support: LegacySupport = (LEGACY_SUPPORT as Map<StableRecordIdentifier, LegacySupport>).get(
|
|
591
|
+
this.___identifier
|
|
592
|
+
)!;
|
|
560
593
|
return support.getHasMany(this.key, options) as Promise<ManyArray> | ManyArray; // this cast is necessary because typescript does not work properly with custom thenables;
|
|
561
594
|
}
|
|
562
595
|
|
|
@@ -570,7 +603,7 @@ export default class HasManyReference {
|
|
|
570
603
|
import Model, { hasMany } from '@ember-data/model';
|
|
571
604
|
|
|
572
605
|
export default class PostModel extends Model {
|
|
573
|
-
@hasMany({ async: true }) comments;
|
|
606
|
+
@hasMany('comment', { async: true, inverse: null }) comments;
|
|
574
607
|
}
|
|
575
608
|
```
|
|
576
609
|
|
|
@@ -611,9 +644,9 @@ export default class HasManyReference {
|
|
|
611
644
|
@return {Promise} a promise that resolves with the ManyArray in this has-many relationship.
|
|
612
645
|
*/
|
|
613
646
|
reload(options?: FindOptions) {
|
|
614
|
-
const support: LegacySupport = (
|
|
615
|
-
|
|
616
|
-
)
|
|
647
|
+
const support: LegacySupport = (LEGACY_SUPPORT as Map<StableRecordIdentifier, LegacySupport>).get(
|
|
648
|
+
this.___identifier
|
|
649
|
+
)!;
|
|
617
650
|
return support.reloadHasMany(this.key, options);
|
|
618
651
|
}
|
|
619
652
|
}
|
|
@@ -6,10 +6,6 @@ import { singularize } from 'ember-inflector';
|
|
|
6
6
|
import type Store from '@ember-data/store';
|
|
7
7
|
import type { RelationshipSchema } from '@ember-data/types/q/record-data-schemas';
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
@module @ember-data/store
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
9
|
function typeForRelationshipMeta(meta) {
|
|
14
10
|
let modelName = dasherize(meta.type || meta.key);
|
|
15
11
|
|
|
@@ -25,10 +21,9 @@ function shouldFindInverse(relationshipMeta) {
|
|
|
25
21
|
return !(options && options.inverse === null);
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
class RelationshipDefinition implements RelationshipSchema {
|
|
29
25
|
declare _type: string;
|
|
30
26
|
declare __inverseKey: string;
|
|
31
|
-
declare __inverseIsAsync: boolean;
|
|
32
27
|
declare __hasCalculatedInverse: boolean;
|
|
33
28
|
declare parentModelName: string;
|
|
34
29
|
declare inverseIsAsync: string | null;
|
|
@@ -37,7 +32,6 @@ export class RelationshipDefinition implements RelationshipSchema {
|
|
|
37
32
|
constructor(meta: any) {
|
|
38
33
|
this._type = '';
|
|
39
34
|
this.__inverseKey = '';
|
|
40
|
-
this.__inverseIsAsync = true;
|
|
41
35
|
this.__hasCalculatedInverse = false;
|
|
42
36
|
this.parentModelName = meta.parentModelName;
|
|
43
37
|
this.meta = meta;
|
|
@@ -74,16 +68,9 @@ export class RelationshipDefinition implements RelationshipSchema {
|
|
|
74
68
|
return this.__inverseKey;
|
|
75
69
|
}
|
|
76
70
|
|
|
77
|
-
_inverseIsAsync(store: Store, modelClass): boolean {
|
|
78
|
-
if (this.__hasCalculatedInverse === false) {
|
|
79
|
-
this._calculateInverse(store, modelClass);
|
|
80
|
-
}
|
|
81
|
-
return this.__inverseIsAsync;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
71
|
_calculateInverse(store: Store, modelClass): void {
|
|
85
72
|
this.__hasCalculatedInverse = true;
|
|
86
|
-
let inverseKey
|
|
73
|
+
let inverseKey;
|
|
87
74
|
let inverse: any = null;
|
|
88
75
|
|
|
89
76
|
if (shouldFindInverse(this.meta)) {
|
|
@@ -94,20 +81,13 @@ export class RelationshipDefinition implements RelationshipSchema {
|
|
|
94
81
|
|
|
95
82
|
if (inverse) {
|
|
96
83
|
inverseKey = inverse.name;
|
|
97
|
-
inverseIsAsync = isRelationshipAsync(inverse);
|
|
98
84
|
} else {
|
|
99
85
|
inverseKey = null;
|
|
100
|
-
inverseIsAsync = false;
|
|
101
86
|
}
|
|
102
87
|
this.__inverseKey = inverseKey;
|
|
103
|
-
this.__inverseIsAsync = inverseIsAsync;
|
|
104
88
|
}
|
|
105
89
|
}
|
|
106
|
-
|
|
107
|
-
function isRelationshipAsync(meta: RelationshipSchema): boolean {
|
|
108
|
-
let inverseAsync = meta.options && meta.options.async;
|
|
109
|
-
return typeof inverseAsync === 'undefined' ? true : inverseAsync;
|
|
110
|
-
}
|
|
90
|
+
export type { RelationshipDefinition };
|
|
111
91
|
|
|
112
92
|
export function relationshipFromMeta(meta: RelationshipSchema): RelationshipDefinition {
|
|
113
93
|
return new RelationshipDefinition(meta);
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ember-data/model",
|
|
3
|
-
"version": "4.8.0-alpha.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "4.8.0-alpha.6",
|
|
4
|
+
"description": "A presentation layer for apps built with @ember-data/store",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
7
7
|
],
|
|
8
|
-
"repository":
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+ssh://git@github.com:emberjs/data.git",
|
|
11
|
+
"directory": "packages/model"
|
|
12
|
+
},
|
|
9
13
|
"license": "MIT",
|
|
10
14
|
"author": "",
|
|
11
15
|
"directories": {
|
|
@@ -18,9 +22,9 @@
|
|
|
18
22
|
"test:node": "mocha"
|
|
19
23
|
},
|
|
20
24
|
"dependencies": {
|
|
21
|
-
"@ember-data/canary-features": "4.8.0-alpha.
|
|
22
|
-
"@ember-data/private-build-infra": "4.8.0-alpha.
|
|
23
|
-
"@ember-data/store": "4.8.0-alpha.
|
|
25
|
+
"@ember-data/canary-features": "4.8.0-alpha.6",
|
|
26
|
+
"@ember-data/private-build-infra": "4.8.0-alpha.6",
|
|
27
|
+
"@ember-data/store": "4.8.0-alpha.6",
|
|
24
28
|
"@ember/edition-utils": "^1.2.0",
|
|
25
29
|
"@ember/string": "^3.0.0",
|
|
26
30
|
"@embroider/macros": "^1.8.3",
|
|
@@ -34,7 +38,7 @@
|
|
|
34
38
|
"inflection": "~1.13.2"
|
|
35
39
|
},
|
|
36
40
|
"devDependencies": {
|
|
37
|
-
"@ember-data/unpublished-test-infra": "4.8.0-alpha.
|
|
41
|
+
"@ember-data/unpublished-test-infra": "4.8.0-alpha.6",
|
|
38
42
|
"@ember/optional-features": "^2.0.0",
|
|
39
43
|
"@ember/test-helpers": "~2.7.0",
|
|
40
44
|
"broccoli-asset-rev": "^3.0.0",
|
|
@@ -67,7 +71,7 @@
|
|
|
67
71
|
"configPath": "tests/dummy/config"
|
|
68
72
|
},
|
|
69
73
|
"volta": {
|
|
70
|
-
"node": "16.
|
|
74
|
+
"node": "16.17.0",
|
|
71
75
|
"yarn": "1.22.19"
|
|
72
76
|
}
|
|
73
77
|
}
|