@ember-data/store 3.28.8 → 3.28.11
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/system/core-store.ts +1 -0
- package/addon/-private/system/model/internal-model.ts +27 -13
- package/addon/-private/system/model/states.js +7 -1
- package/addon/-private/system/record-array-manager.js +1 -1
- package/addon/-private/system/record-notification-manager.ts +58 -24
- package/addon/-private/system/references/{belongs-to.js → belongs-to.ts} +100 -16
- package/addon/-private/system/references/{has-many.js → has-many.ts} +156 -45
- package/addon/-private/system/references/record.ts +54 -7
- package/addon/-private/system/references/reference.ts +1 -1
- package/addon/-private/ts-interfaces/ds-model.ts +1 -0
- package/index.js +3 -0
- package/package.json +5 -4
|
@@ -2500,6 +2500,7 @@ abstract class CoreStore extends Service {
|
|
|
2500
2500
|
const factory = internalModelFactoryFor(this);
|
|
2501
2501
|
|
|
2502
2502
|
if (modelName === undefined) {
|
|
2503
|
+
this._notificationManager.destroy();
|
|
2503
2504
|
factory.clear();
|
|
2504
2505
|
} else {
|
|
2505
2506
|
let normalizedModelName = normalizeModelName(modelName);
|
|
@@ -28,6 +28,8 @@ import Snapshot from '../snapshot';
|
|
|
28
28
|
import { internalModelFactoryFor, setRecordIdentifier } from '../store/internal-model-factory';
|
|
29
29
|
import RootState from './states';
|
|
30
30
|
|
|
31
|
+
type DSModel = import('../../ts-interfaces/ds-model').DSModel;
|
|
32
|
+
|
|
31
33
|
type BelongsToRelationship = import('@ember-data/record-data/-private').BelongsToRelationship;
|
|
32
34
|
type ManyRelationship = import('@ember-data/record-data/-private').ManyRelationship;
|
|
33
35
|
|
|
@@ -130,7 +132,7 @@ export default class InternalModel {
|
|
|
130
132
|
declare _deferredTriggers: any;
|
|
131
133
|
declare __recordArrays: any;
|
|
132
134
|
declare references: any;
|
|
133
|
-
declare _recordReference:
|
|
135
|
+
declare _recordReference: RecordReference;
|
|
134
136
|
declare _manyArrayCache: ConfidentDict<ManyArray>;
|
|
135
137
|
|
|
136
138
|
declare _relationshipPromisesCache: ConfidentDict<RSVP.Promise<any>>;
|
|
@@ -202,7 +204,7 @@ export default class InternalModel {
|
|
|
202
204
|
}
|
|
203
205
|
}
|
|
204
206
|
|
|
205
|
-
get recordReference() {
|
|
207
|
+
get recordReference(): RecordReference {
|
|
206
208
|
if (this._recordReference === null) {
|
|
207
209
|
this._recordReference = new RecordReference(this.store, this.identifier);
|
|
208
210
|
}
|
|
@@ -294,7 +296,7 @@ export default class InternalModel {
|
|
|
294
296
|
}
|
|
295
297
|
}
|
|
296
298
|
|
|
297
|
-
getRecord(properties?) {
|
|
299
|
+
getRecord(properties?): Object {
|
|
298
300
|
if (!this._record && !this._isDematerializing) {
|
|
299
301
|
let { store } = this;
|
|
300
302
|
|
|
@@ -616,7 +618,7 @@ export default class InternalModel {
|
|
|
616
618
|
"' with id " +
|
|
617
619
|
parentInternalModel.id +
|
|
618
620
|
' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`belongsTo({ async: true })`)',
|
|
619
|
-
toReturn === null || !toReturn.
|
|
621
|
+
toReturn === null || !(toReturn as DSModel).isEmpty
|
|
620
622
|
);
|
|
621
623
|
return toReturn;
|
|
622
624
|
}
|
|
@@ -675,7 +677,7 @@ export default class InternalModel {
|
|
|
675
677
|
assert(`hasMany only works with the @ember-data/record-data package`);
|
|
676
678
|
}
|
|
677
679
|
|
|
678
|
-
getHasMany(key: string, options) {
|
|
680
|
+
getHasMany(key: string, options?) {
|
|
679
681
|
if (HAS_RECORD_DATA_PACKAGE) {
|
|
680
682
|
const graphFor = require('@ember-data/record-data/-private').graphFor;
|
|
681
683
|
const relationship = graphFor(this.store).get(this.identifier, key);
|
|
@@ -793,11 +795,22 @@ export default class InternalModel {
|
|
|
793
795
|
!this._record || this._record.get('isDestroyed') || this._record.get('isDestroying')
|
|
794
796
|
);
|
|
795
797
|
this.isDestroying = true;
|
|
798
|
+
if (this._recordReference) {
|
|
799
|
+
this._recordReference.destroy();
|
|
800
|
+
}
|
|
801
|
+
this._recordReference = null;
|
|
796
802
|
let cache = this._manyArrayCache;
|
|
797
803
|
Object.keys(cache).forEach((key) => {
|
|
798
804
|
cache[key].destroy();
|
|
799
805
|
delete cache[key];
|
|
800
806
|
});
|
|
807
|
+
if (this.references) {
|
|
808
|
+
cache = this.references;
|
|
809
|
+
Object.keys(cache).forEach((key) => {
|
|
810
|
+
cache[key].destroy();
|
|
811
|
+
delete cache[key];
|
|
812
|
+
});
|
|
813
|
+
}
|
|
801
814
|
|
|
802
815
|
internalModelFactoryFor(this.store).remove(this);
|
|
803
816
|
this._isDestroyed = true;
|
|
@@ -806,6 +819,7 @@ export default class InternalModel {
|
|
|
806
819
|
setupData(data) {
|
|
807
820
|
let changedKeys = this._recordData.pushData(data, this.hasRecord);
|
|
808
821
|
if (this.hasRecord) {
|
|
822
|
+
// TODO @runspired should this be going through the notification manager?
|
|
809
823
|
this._record._notifyProperties(changedKeys);
|
|
810
824
|
}
|
|
811
825
|
this.send('pushedData');
|
|
@@ -966,10 +980,10 @@ export default class InternalModel {
|
|
|
966
980
|
this.store._notificationManager.notify(this.identifier, 'state');
|
|
967
981
|
} else {
|
|
968
982
|
if (!key || key === 'isNew') {
|
|
969
|
-
this.getRecord().notifyPropertyChange('isNew');
|
|
983
|
+
(this.getRecord() as DSModel).notifyPropertyChange('isNew');
|
|
970
984
|
}
|
|
971
985
|
if (!key || key === 'isDeleted') {
|
|
972
|
-
this.getRecord().notifyPropertyChange('isDeleted');
|
|
986
|
+
(this.getRecord() as DSModel).notifyPropertyChange('isDeleted');
|
|
973
987
|
}
|
|
974
988
|
}
|
|
975
989
|
}
|
|
@@ -1273,12 +1287,12 @@ export default class InternalModel {
|
|
|
1273
1287
|
if (this._recordData.getErrors) {
|
|
1274
1288
|
return this._recordData.getErrors(this.identifier).length > 0;
|
|
1275
1289
|
} else {
|
|
1276
|
-
let errors =
|
|
1277
|
-
return errors.
|
|
1290
|
+
let errors = (this.getRecord() as DSModel).errors;
|
|
1291
|
+
return errors.length > 0;
|
|
1278
1292
|
}
|
|
1279
1293
|
} else {
|
|
1280
|
-
let errors =
|
|
1281
|
-
return errors.
|
|
1294
|
+
let errors = (this.getRecord() as DSModel).errors;
|
|
1295
|
+
return errors.length > 0;
|
|
1282
1296
|
}
|
|
1283
1297
|
}
|
|
1284
1298
|
|
|
@@ -1293,7 +1307,7 @@ export default class InternalModel {
|
|
|
1293
1307
|
if (!this._recordData.getErrors) {
|
|
1294
1308
|
for (attribute in parsedErrors) {
|
|
1295
1309
|
if (hasOwnProperty.call(parsedErrors, attribute)) {
|
|
1296
|
-
this.getRecord().errors._add(attribute, parsedErrors[attribute]);
|
|
1310
|
+
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1297
1311
|
}
|
|
1298
1312
|
}
|
|
1299
1313
|
}
|
|
@@ -1313,7 +1327,7 @@ export default class InternalModel {
|
|
|
1313
1327
|
|
|
1314
1328
|
for (attribute in parsedErrors) {
|
|
1315
1329
|
if (hasOwnProperty.call(parsedErrors, attribute)) {
|
|
1316
|
-
this.getRecord().errors._add(attribute, parsedErrors[attribute]);
|
|
1330
|
+
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1317
1331
|
}
|
|
1318
1332
|
}
|
|
1319
1333
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { assert } from '@ember/debug';
|
|
5
5
|
|
|
6
|
-
import { REQUEST_SERVICE } from '@ember-data/canary-features';
|
|
6
|
+
import { CUSTOM_MODEL_CLASS, REQUEST_SERVICE } from '@ember-data/canary-features';
|
|
7
7
|
/*
|
|
8
8
|
This file encapsulates the various states that a record can transition
|
|
9
9
|
through during its lifecycle.
|
|
@@ -431,6 +431,12 @@ createdState.uncommitted.rollback = function (internalModel) {
|
|
|
431
431
|
};
|
|
432
432
|
|
|
433
433
|
createdState.uncommitted.pushedData = function (internalModel) {
|
|
434
|
+
// TODO @runspired consider where to do this once we kill off state machine
|
|
435
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
436
|
+
internalModel.store._notificationManager.notify(internalModel.identifier, 'identity');
|
|
437
|
+
} else {
|
|
438
|
+
internalModel.notifyPropertyChange('id');
|
|
439
|
+
}
|
|
434
440
|
internalModel.transitionTo('loaded.updated.uncommitted');
|
|
435
441
|
internalModel.triggerLater('didLoad');
|
|
436
442
|
};
|
|
@@ -27,7 +27,7 @@ export function recordArraysForIdentifier(identifierOrInternalModel) {
|
|
|
27
27
|
return RecordArraysCache.get(identifierOrInternalModel);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const pendingForIdentifier = new Set(
|
|
30
|
+
const pendingForIdentifier = new Set();
|
|
31
31
|
const IMDematerializing = new WeakMap();
|
|
32
32
|
|
|
33
33
|
const getIdentifier = function getIdentifier(identifierOrInternalModel) {
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assert } from '@ember/debug';
|
|
2
|
+
import { DEBUG } from '@glimmer/env';
|
|
3
|
+
|
|
4
|
+
import isStableIdentifier from '../identifiers/is-stable-identifier';
|
|
2
5
|
|
|
3
6
|
type CoreStore = import('./core-store').default;
|
|
4
|
-
type RecordIdentifier = import('../ts-interfaces/identifier').RecordIdentifier;
|
|
5
7
|
type StableRecordIdentifier = import('../ts-interfaces/identifier').StableRecordIdentifier;
|
|
6
8
|
|
|
7
|
-
type UnsubscribeToken =
|
|
9
|
+
type UnsubscribeToken = object;
|
|
10
|
+
let tokenId = 0;
|
|
8
11
|
|
|
9
|
-
const Cache = new
|
|
10
|
-
const Tokens = new
|
|
12
|
+
const Cache = new Map<StableRecordIdentifier, Map<UnsubscribeToken, NotificationCallback>>();
|
|
13
|
+
const Tokens = new Map<UnsubscribeToken, StableRecordIdentifier>();
|
|
11
14
|
|
|
12
15
|
export type NotificationType =
|
|
13
16
|
| 'attributes'
|
|
@@ -20,42 +23,73 @@ export type NotificationType =
|
|
|
20
23
|
| 'property'; // 'property' is an internal EmberData only transition period concept.
|
|
21
24
|
|
|
22
25
|
export interface NotificationCallback {
|
|
23
|
-
(identifier:
|
|
24
|
-
(identifier:
|
|
26
|
+
(identifier: StableRecordIdentifier, notificationType: 'attributes' | 'relationships', key?: string): void;
|
|
27
|
+
(identifier: StableRecordIdentifier, notificationType: 'errors' | 'meta' | 'identity' | 'state'): void;
|
|
25
28
|
(identifier: StableRecordIdentifier, notificationType: NotificationType, key?: string): void;
|
|
26
29
|
}
|
|
27
30
|
|
|
31
|
+
// TODO this isn't importable anyway, remove and use a map on the manager?
|
|
28
32
|
export function unsubscribe(token: UnsubscribeToken) {
|
|
29
33
|
let identifier = Tokens.get(token);
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
|
|
35
|
+
if (identifier) {
|
|
36
|
+
Tokens.delete(token);
|
|
37
|
+
const map = Cache.get(identifier);
|
|
38
|
+
map?.delete(token);
|
|
32
39
|
}
|
|
33
|
-
Tokens.delete(token);
|
|
34
|
-
Cache.delete(identifier);
|
|
35
40
|
}
|
|
36
41
|
/*
|
|
37
42
|
Currently only support a single callback per identifier
|
|
38
43
|
*/
|
|
39
44
|
export default class NotificationManager {
|
|
40
|
-
|
|
45
|
+
declare store: CoreStore;
|
|
46
|
+
constructor(store: CoreStore) {
|
|
47
|
+
this.store = store;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
subscribe(identifier: StableRecordIdentifier, callback: NotificationCallback): UnsubscribeToken {
|
|
51
|
+
assert(`Expected to receive a stable Identifier to subscribe to`, isStableIdentifier(identifier));
|
|
52
|
+
let map = Cache.get(identifier);
|
|
41
53
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
if (!map) {
|
|
55
|
+
map = new Map();
|
|
56
|
+
Cache.set(identifier, map);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let unsubToken = DEBUG ? { _tokenRef: tokenId++ } : {};
|
|
60
|
+
map.set(unsubToken, callback);
|
|
61
|
+
Tokens.set(unsubToken, identifier);
|
|
47
62
|
return unsubToken;
|
|
48
63
|
}
|
|
49
64
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
unsubscribe(token: UnsubscribeToken) {
|
|
66
|
+
unsubscribe(token);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// deactivated type signature overloads because pass-through was failing to match any. Bring back if possible.
|
|
70
|
+
// notify(identifier: StableRecordIdentifier, value: 'attributes' | 'relationships', key?: string): boolean;
|
|
71
|
+
// notify(identifier: StableRecordIdentifier, value: 'errors' | 'meta' | 'identity' | 'state'): boolean;
|
|
72
|
+
notify(identifier: StableRecordIdentifier, value: NotificationType, key?: string): boolean {
|
|
73
|
+
assert(
|
|
74
|
+
`Notify does not accept a key argument for the namespace '${value}'. Received key '${key}'.`,
|
|
75
|
+
!key || value === 'attributes' || value === 'relationships'
|
|
76
|
+
);
|
|
77
|
+
if (!isStableIdentifier(identifier)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let callbackMap = Cache.get(identifier);
|
|
82
|
+
if (!callbackMap || !callbackMap.size) {
|
|
56
83
|
return false;
|
|
57
84
|
}
|
|
58
|
-
|
|
85
|
+
callbackMap.forEach((cb) => {
|
|
86
|
+
cb(identifier, value, key);
|
|
87
|
+
});
|
|
59
88
|
return true;
|
|
60
89
|
}
|
|
90
|
+
|
|
91
|
+
destroy() {
|
|
92
|
+
Tokens.clear();
|
|
93
|
+
Cache.clear();
|
|
94
|
+
}
|
|
61
95
|
}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { deprecate } from '@ember/debug';
|
|
2
|
+
import { dependentKeyCompat } from '@ember/object/compat';
|
|
3
|
+
import { cached, tracked } from '@glimmer/tracking';
|
|
2
4
|
|
|
3
5
|
import { resolve } from 'rsvp';
|
|
4
6
|
|
|
7
|
+
import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
|
|
5
8
|
import { DEPRECATE_BELONGS_TO_REFERENCE_PUSH } from '@ember-data/private-build-infra/deprecations';
|
|
6
9
|
import { assertPolymorphicType } from '@ember-data/store/-debug';
|
|
7
10
|
|
|
11
|
+
import { unsubscribe } from '../record-notification-manager';
|
|
8
12
|
import { internalModelFactoryFor, peekRecordIdentifier, recordIdentifierFor } from '../store/internal-model-factory';
|
|
9
13
|
import Reference from './reference';
|
|
10
14
|
|
|
15
|
+
type RecordReference = import('./record').default;
|
|
16
|
+
type NotificationType = import('../record-notification-manager').NotificationType;
|
|
17
|
+
type CoreStore = import('../core-store').default;
|
|
18
|
+
type StableRecordIdentifier = import('../../ts-interfaces/identifier').StableRecordIdentifier;
|
|
19
|
+
type SingleResourceDocument = import('../../ts-interfaces/ember-data-json-api').SingleResourceDocument;
|
|
20
|
+
|
|
21
|
+
type BelongsToRelationship = import('@ember-data/record-data/-private').BelongsToRelationship;
|
|
11
22
|
/**
|
|
12
23
|
@module @ember-data/store
|
|
13
24
|
*/
|
|
@@ -22,17 +33,84 @@ import Reference from './reference';
|
|
|
22
33
|
@extends Reference
|
|
23
34
|
*/
|
|
24
35
|
export default class BelongsToReference extends Reference {
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
declare key: string;
|
|
37
|
+
declare belongsToRelationship: BelongsToRelationship;
|
|
38
|
+
declare type: string;
|
|
39
|
+
declare parent: RecordReference;
|
|
40
|
+
declare parentIdentifier: StableRecordIdentifier;
|
|
41
|
+
|
|
42
|
+
// unsubscribe tokens given to us by the notification manager
|
|
43
|
+
#token!: object;
|
|
44
|
+
#relatedToken: object | null = null;
|
|
45
|
+
|
|
46
|
+
@tracked _ref = 0;
|
|
47
|
+
|
|
48
|
+
constructor(
|
|
49
|
+
store: CoreStore,
|
|
50
|
+
parentIdentifier: StableRecordIdentifier,
|
|
51
|
+
belongsToRelationship: BelongsToRelationship,
|
|
52
|
+
key: string
|
|
53
|
+
) {
|
|
54
|
+
super(store, parentIdentifier);
|
|
27
55
|
this.key = key;
|
|
28
56
|
this.belongsToRelationship = belongsToRelationship;
|
|
29
57
|
this.type = belongsToRelationship.definition.type;
|
|
30
|
-
|
|
31
|
-
this.
|
|
58
|
+
const parent = internalModelFactoryFor(store).peek(parentIdentifier);
|
|
59
|
+
this.parent = parent!.recordReference;
|
|
60
|
+
this.parentIdentifier = parentIdentifier;
|
|
61
|
+
|
|
62
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
63
|
+
this.#token = store._notificationManager.subscribe(
|
|
64
|
+
parentIdentifier,
|
|
65
|
+
(_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
|
|
66
|
+
if ((bucket === 'relationships' || bucket === 'property') && notifiedKey === key) {
|
|
67
|
+
this._ref++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
32
72
|
|
|
33
73
|
// TODO inverse
|
|
34
74
|
}
|
|
35
75
|
|
|
76
|
+
destroy() {
|
|
77
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
78
|
+
unsubscribe(this.#token);
|
|
79
|
+
this.#token = null as unknown as object;
|
|
80
|
+
if (this.#relatedToken) {
|
|
81
|
+
unsubscribe(this.#relatedToken);
|
|
82
|
+
this.#relatedToken = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@cached
|
|
88
|
+
@dependentKeyCompat
|
|
89
|
+
get _relatedIdentifier(): StableRecordIdentifier | null {
|
|
90
|
+
this._ref; // consume the tracked prop
|
|
91
|
+
if (this.#relatedToken) {
|
|
92
|
+
unsubscribe(this.#relatedToken);
|
|
93
|
+
this.#relatedToken = null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let resource = this._resource();
|
|
97
|
+
if (resource && resource.data) {
|
|
98
|
+
const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resource.data);
|
|
99
|
+
this.#relatedToken = this.store._notificationManager.subscribe(
|
|
100
|
+
identifier,
|
|
101
|
+
(_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
|
|
102
|
+
if (bucket === 'identity' || ((bucket === 'attributes' || bucket === 'property') && notifiedKey === 'id')) {
|
|
103
|
+
this._ref++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
return identifier;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
36
114
|
/**
|
|
37
115
|
The `id` of the record that this reference refers to. Together, the
|
|
38
116
|
`type()` and `id()` methods form a composite key for the identity
|
|
@@ -73,13 +151,18 @@ export default class BelongsToReference extends Reference {
|
|
|
73
151
|
@public
|
|
74
152
|
@return {String} The id of the record in this belongsTo relationship.
|
|
75
153
|
*/
|
|
76
|
-
id() {
|
|
77
|
-
|
|
154
|
+
id(): string | null {
|
|
155
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
156
|
+
return this._relatedIdentifier?.id || null;
|
|
157
|
+
}
|
|
78
158
|
let resource = this._resource();
|
|
79
159
|
if (resource && resource.data) {
|
|
80
|
-
|
|
160
|
+
const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resource.data);
|
|
161
|
+
|
|
162
|
+
return identifier.id;
|
|
81
163
|
}
|
|
82
|
-
|
|
164
|
+
|
|
165
|
+
return null;
|
|
83
166
|
}
|
|
84
167
|
|
|
85
168
|
_resource() {
|
|
@@ -132,10 +215,10 @@ export default class BelongsToReference extends Reference {
|
|
|
132
215
|
@param {Object|Promise} objectOrPromise a promise that resolves to a JSONAPI document object describing the new value of this relationship.
|
|
133
216
|
@return {Promise<record>} A promise that resolves with the new value in this belongs-to relationship.
|
|
134
217
|
*/
|
|
135
|
-
push(objectOrPromise) {
|
|
218
|
+
async push(objectOrPromise: Object | SingleResourceDocument): Promise<Object> {
|
|
136
219
|
// TODO deprecate thenable support
|
|
137
220
|
return resolve(objectOrPromise).then((data) => {
|
|
138
|
-
let record;
|
|
221
|
+
let record: Object;
|
|
139
222
|
|
|
140
223
|
if (DEPRECATE_BELONGS_TO_REFERENCE_PUSH && peekRecordIdentifier(data)) {
|
|
141
224
|
deprecate('Pushing a record into a BelongsToReference is deprecated', false, {
|
|
@@ -147,15 +230,16 @@ export default class BelongsToReference extends Reference {
|
|
|
147
230
|
enabled: '3.16',
|
|
148
231
|
},
|
|
149
232
|
});
|
|
150
|
-
record = data;
|
|
233
|
+
record = data as Object;
|
|
151
234
|
} else {
|
|
152
|
-
record = this.store.push(data);
|
|
235
|
+
record = this.store.push(data as SingleResourceDocument);
|
|
153
236
|
}
|
|
154
237
|
|
|
238
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
155
239
|
assertPolymorphicType(
|
|
156
240
|
this.belongsToRelationship.identifier,
|
|
157
241
|
this.belongsToRelationship.definition,
|
|
158
|
-
record
|
|
242
|
+
recordIdentifierFor(record),
|
|
159
243
|
this.store
|
|
160
244
|
);
|
|
161
245
|
|
|
@@ -223,7 +307,7 @@ export default class BelongsToReference extends Reference {
|
|
|
223
307
|
@public
|
|
224
308
|
@return {Model} the record in this relationship
|
|
225
309
|
*/
|
|
226
|
-
value() {
|
|
310
|
+
value(): Object | null {
|
|
227
311
|
let resource = this._resource();
|
|
228
312
|
if (resource && resource.data) {
|
|
229
313
|
let inverseInternalModel = this.store._internalModelForResource(resource.data);
|
|
@@ -299,7 +383,7 @@ export default class BelongsToReference extends Reference {
|
|
|
299
383
|
*/
|
|
300
384
|
load(options) {
|
|
301
385
|
let parentInternalModel = internalModelFactoryFor(this.store).peek(this.parentIdentifier);
|
|
302
|
-
return parentInternalModel
|
|
386
|
+
return parentInternalModel!.getBelongsTo(this.key, options);
|
|
303
387
|
}
|
|
304
388
|
|
|
305
389
|
/**
|
|
@@ -354,7 +438,7 @@ export default class BelongsToReference extends Reference {
|
|
|
354
438
|
*/
|
|
355
439
|
reload(options) {
|
|
356
440
|
let parentInternalModel = internalModelFactoryFor(this.store).peek(this.parentIdentifier);
|
|
357
|
-
return parentInternalModel
|
|
441
|
+
return parentInternalModel!.reloadBelongsTo(this.key, options).then((internalModel) => {
|
|
358
442
|
return this.value();
|
|
359
443
|
});
|
|
360
444
|
}
|
|
@@ -1,12 +1,26 @@
|
|
|
1
|
+
import { dependentKeyCompat } from '@ember/object/compat';
|
|
1
2
|
import { DEBUG } from '@glimmer/env';
|
|
3
|
+
import { cached, tracked } from '@glimmer/tracking';
|
|
2
4
|
|
|
3
5
|
import { resolve } from 'rsvp';
|
|
4
6
|
|
|
7
|
+
import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
|
|
5
8
|
import { assertPolymorphicType } from '@ember-data/store/-debug';
|
|
6
9
|
|
|
10
|
+
import { unsubscribe } from '../record-notification-manager';
|
|
7
11
|
import { internalModelFactoryFor, recordIdentifierFor } from '../store/internal-model-factory';
|
|
8
12
|
import Reference, { internalModelForReference } from './reference';
|
|
9
13
|
|
|
14
|
+
type RecordReference = import('./record').default;
|
|
15
|
+
type NotificationType = import('../record-notification-manager').NotificationType;
|
|
16
|
+
type CoreStore = import('../core-store').default;
|
|
17
|
+
type StableRecordIdentifier = import('../../ts-interfaces/identifier').StableRecordIdentifier;
|
|
18
|
+
type CollectionResourceDocument = import('../../ts-interfaces/ember-data-json-api').CollectionResourceDocument;
|
|
19
|
+
type ExistingResourceObject = import('../../ts-interfaces/ember-data-json-api').ExistingResourceObject;
|
|
20
|
+
type SingleResourceDocument = import('../../ts-interfaces/ember-data-json-api').SingleResourceDocument;
|
|
21
|
+
|
|
22
|
+
type ManyRelationship = import('@ember-data/record-data/-private').ManyRelationship;
|
|
23
|
+
|
|
10
24
|
/**
|
|
11
25
|
@module @ember-data/store
|
|
12
26
|
*/
|
|
@@ -20,17 +34,102 @@ import Reference, { internalModelForReference } from './reference';
|
|
|
20
34
|
@extends Reference
|
|
21
35
|
*/
|
|
22
36
|
export default class HasManyReference extends Reference {
|
|
23
|
-
|
|
24
|
-
|
|
37
|
+
declare key: string;
|
|
38
|
+
declare hasManyRelationship: ManyRelationship;
|
|
39
|
+
declare type: string;
|
|
40
|
+
declare parent: RecordReference;
|
|
41
|
+
declare parentIdentifier: StableRecordIdentifier;
|
|
42
|
+
|
|
43
|
+
// unsubscribe tokens given to us by the notification manager
|
|
44
|
+
#token!: Object;
|
|
45
|
+
#relatedTokenMap!: Map<StableRecordIdentifier, Object>;
|
|
46
|
+
|
|
47
|
+
@tracked _ref = 0;
|
|
48
|
+
|
|
49
|
+
constructor(
|
|
50
|
+
store: CoreStore,
|
|
51
|
+
parentIdentifier: StableRecordIdentifier,
|
|
52
|
+
hasManyRelationship: ManyRelationship,
|
|
53
|
+
key: string
|
|
54
|
+
) {
|
|
55
|
+
super(store, parentIdentifier);
|
|
25
56
|
this.key = key;
|
|
26
57
|
this.hasManyRelationship = hasManyRelationship;
|
|
27
58
|
this.type = hasManyRelationship.definition.type;
|
|
28
59
|
|
|
29
|
-
this.parent = internalModelFactoryFor(store).peek(
|
|
60
|
+
this.parent = internalModelFactoryFor(store).peek(parentIdentifier)!.recordReference;
|
|
30
61
|
|
|
62
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
63
|
+
this.#token = store._notificationManager.subscribe(
|
|
64
|
+
parentIdentifier,
|
|
65
|
+
(_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
|
|
66
|
+
if ((bucket === 'relationships' || bucket === 'property') && notifiedKey === key) {
|
|
67
|
+
this._ref++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
this.#relatedTokenMap = new Map();
|
|
72
|
+
}
|
|
31
73
|
// TODO inverse
|
|
32
74
|
}
|
|
33
75
|
|
|
76
|
+
destroy() {
|
|
77
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
78
|
+
unsubscribe(this.#token);
|
|
79
|
+
this.#token = null as unknown as object;
|
|
80
|
+
this.#relatedTokenMap.forEach((token) => {
|
|
81
|
+
unsubscribe(token);
|
|
82
|
+
});
|
|
83
|
+
this.#relatedTokenMap.clear();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@cached
|
|
88
|
+
@dependentKeyCompat
|
|
89
|
+
get _relatedIdentifiers(): StableRecordIdentifier[] {
|
|
90
|
+
this._ref; // consume the tracked prop
|
|
91
|
+
|
|
92
|
+
let resource = this._resource();
|
|
93
|
+
|
|
94
|
+
let map = this.#relatedTokenMap;
|
|
95
|
+
this.#relatedTokenMap = new Map();
|
|
96
|
+
|
|
97
|
+
if (resource && resource.data) {
|
|
98
|
+
return resource.data.map((resourceIdentifier) => {
|
|
99
|
+
const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
|
|
100
|
+
|
|
101
|
+
let token = map.get(identifier);
|
|
102
|
+
|
|
103
|
+
if (token) {
|
|
104
|
+
map.delete(identifier);
|
|
105
|
+
} else {
|
|
106
|
+
token = this.store._notificationManager.subscribe(
|
|
107
|
+
identifier,
|
|
108
|
+
(_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
|
|
109
|
+
if (
|
|
110
|
+
bucket === 'identity' ||
|
|
111
|
+
((bucket === 'attributes' || bucket === 'property') && notifiedKey === 'id')
|
|
112
|
+
) {
|
|
113
|
+
this._ref++;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
this.#relatedTokenMap.set(identifier, token);
|
|
120
|
+
|
|
121
|
+
return identifier;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
map.forEach((token) => {
|
|
126
|
+
this.store._notificationManager.unsubscribe(token);
|
|
127
|
+
});
|
|
128
|
+
map.clear();
|
|
129
|
+
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
|
|
34
133
|
_resource() {
|
|
35
134
|
return this.recordData.getHasMany(this.key);
|
|
36
135
|
}
|
|
@@ -77,7 +176,7 @@ export default class HasManyReference extends Reference {
|
|
|
77
176
|
@public
|
|
78
177
|
@return {String} The name of the remote type. This should either be `link` or `ids`
|
|
79
178
|
*/
|
|
80
|
-
remoteType() {
|
|
179
|
+
remoteType(): 'link' | 'ids' {
|
|
81
180
|
let value = this._resource();
|
|
82
181
|
if (value && value.links && value.links.related) {
|
|
83
182
|
return 'link';
|
|
@@ -121,15 +220,22 @@ export default class HasManyReference extends Reference {
|
|
|
121
220
|
@public
|
|
122
221
|
@return {Array} The ids in this has-many relationship
|
|
123
222
|
*/
|
|
124
|
-
ids() {
|
|
223
|
+
ids(): Array<string | null> {
|
|
224
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
225
|
+
return this._relatedIdentifiers.map((identifier) => identifier.id);
|
|
226
|
+
}
|
|
227
|
+
|
|
125
228
|
let resource = this._resource();
|
|
126
229
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
230
|
+
if (resource && resource.data) {
|
|
231
|
+
return resource.data.map((resourceIdentifier) => {
|
|
232
|
+
const identifier = this.store.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
|
|
233
|
+
|
|
234
|
+
return identifier.id;
|
|
235
|
+
});
|
|
130
236
|
}
|
|
131
237
|
|
|
132
|
-
return
|
|
238
|
+
return [];
|
|
133
239
|
}
|
|
134
240
|
|
|
135
241
|
/**
|
|
@@ -177,45 +283,50 @@ export default class HasManyReference extends Reference {
|
|
|
177
283
|
@param {Array|Promise} objectOrPromise a promise that resolves to a JSONAPI document object describing the new value of this relationship.
|
|
178
284
|
@return {ManyArray}
|
|
179
285
|
*/
|
|
180
|
-
push(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
286
|
+
async push(
|
|
287
|
+
objectOrPromise: ExistingResourceObject[] | CollectionResourceDocument | { data: SingleResourceDocument[] }
|
|
288
|
+
): Promise<any> {
|
|
289
|
+
const payload = await resolve(objectOrPromise);
|
|
290
|
+
let array: Array<ExistingResourceObject | SingleResourceDocument>;
|
|
291
|
+
|
|
292
|
+
if (!Array.isArray(payload) && typeof payload === 'object' && Array.isArray(payload.data)) {
|
|
293
|
+
array = payload.data;
|
|
294
|
+
} else {
|
|
295
|
+
array = payload as ExistingResourceObject[];
|
|
296
|
+
}
|
|
187
297
|
|
|
188
|
-
|
|
298
|
+
const internalModel = internalModelForReference(this)!;
|
|
299
|
+
const { store } = this;
|
|
189
300
|
|
|
190
|
-
|
|
191
|
-
|
|
301
|
+
let identifiers = array.map((obj) => {
|
|
302
|
+
let record;
|
|
303
|
+
if ('data' in obj) {
|
|
304
|
+
// TODO deprecate pushing non-valid JSON:API here
|
|
305
|
+
record = store.push(obj);
|
|
306
|
+
} else {
|
|
307
|
+
record = store.push({ data: obj });
|
|
308
|
+
}
|
|
192
309
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
return recordIdentifierFor(record);
|
|
203
|
-
});
|
|
310
|
+
if (DEBUG) {
|
|
311
|
+
let relationshipMeta = this.hasManyRelationship.definition;
|
|
312
|
+
let identifier = this.hasManyRelationship.identifier;
|
|
313
|
+
assertPolymorphicType(identifier, relationshipMeta, recordIdentifierFor(record), store);
|
|
314
|
+
}
|
|
315
|
+
return recordIdentifierFor(record);
|
|
316
|
+
});
|
|
204
317
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
});
|
|
318
|
+
const { graph, identifier } = this.hasManyRelationship;
|
|
319
|
+
store._backburner.join(() => {
|
|
320
|
+
graph.push({
|
|
321
|
+
op: 'replaceRelatedRecords',
|
|
322
|
+
record: identifier,
|
|
323
|
+
field: this.key,
|
|
324
|
+
value: identifiers,
|
|
213
325
|
});
|
|
214
|
-
|
|
215
|
-
return internalModel.getHasMany(this.key);
|
|
216
|
-
// TODO IGOR it seems wrong that we were returning the many array here
|
|
217
|
-
//return this.hasManyRelationship.manyArray;
|
|
218
326
|
});
|
|
327
|
+
|
|
328
|
+
// TODO IGOR it seems wrong that we were returning the many array here
|
|
329
|
+
return internalModel.getHasMany(this.key);
|
|
219
330
|
}
|
|
220
331
|
|
|
221
332
|
_isLoaded() {
|
|
@@ -275,7 +386,7 @@ export default class HasManyReference extends Reference {
|
|
|
275
386
|
@return {ManyArray}
|
|
276
387
|
*/
|
|
277
388
|
value() {
|
|
278
|
-
let internalModel = internalModelForReference(this)
|
|
389
|
+
let internalModel = internalModelForReference(this)!;
|
|
279
390
|
if (this._isLoaded()) {
|
|
280
391
|
return internalModel.getManyArray(this.key);
|
|
281
392
|
}
|
|
@@ -348,7 +459,7 @@ export default class HasManyReference extends Reference {
|
|
|
348
459
|
this has-many relationship.
|
|
349
460
|
*/
|
|
350
461
|
load(options) {
|
|
351
|
-
let internalModel = internalModelForReference(this)
|
|
462
|
+
let internalModel = internalModelForReference(this)!;
|
|
352
463
|
return internalModel.getHasMany(this.key, options);
|
|
353
464
|
}
|
|
354
465
|
|
|
@@ -403,7 +514,7 @@ export default class HasManyReference extends Reference {
|
|
|
403
514
|
@return {Promise} a promise that resolves with the ManyArray in this has-many relationship.
|
|
404
515
|
*/
|
|
405
516
|
reload(options) {
|
|
406
|
-
let internalModel = internalModelForReference(this)
|
|
517
|
+
let internalModel = internalModelForReference(this)!;
|
|
407
518
|
return internalModel.reloadHasMany(this.key, options);
|
|
408
519
|
}
|
|
409
520
|
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import { dependentKeyCompat } from '@ember/object/compat';
|
|
2
|
+
import { cached, tracked } from '@glimmer/tracking';
|
|
3
|
+
|
|
1
4
|
import RSVP, { resolve } from 'rsvp';
|
|
2
5
|
|
|
6
|
+
import { CUSTOM_MODEL_CLASS } from '@ember-data/canary-features';
|
|
7
|
+
|
|
8
|
+
import { unsubscribe } from '../record-notification-manager';
|
|
3
9
|
import Reference, { internalModelForReference, REFERENCE_CACHE } from './reference';
|
|
4
10
|
|
|
11
|
+
type NotificationType = import('../record-notification-manager').NotificationType;
|
|
12
|
+
|
|
13
|
+
type CoreStore = import('../core-store').default;
|
|
5
14
|
type SingleResourceDocument = import('../../ts-interfaces/ember-data-json-api').SingleResourceDocument;
|
|
6
15
|
type RecordInstance = import('../../ts-interfaces/record-instance').RecordInstance;
|
|
7
16
|
type StableRecordIdentifier = import('../../ts-interfaces/identifier').StableRecordIdentifier;
|
|
@@ -19,11 +28,39 @@ type StableRecordIdentifier = import('../../ts-interfaces/identifier').StableRec
|
|
|
19
28
|
@extends Reference
|
|
20
29
|
*/
|
|
21
30
|
export default class RecordReference extends Reference {
|
|
31
|
+
// unsubscribe token given to us by the notification manager
|
|
32
|
+
#token!: Object;
|
|
33
|
+
|
|
34
|
+
@tracked _ref = 0;
|
|
35
|
+
|
|
36
|
+
constructor(public store: CoreStore, identifier: StableRecordIdentifier) {
|
|
37
|
+
super(store, identifier);
|
|
38
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
39
|
+
this.#token = store._notificationManager.subscribe(
|
|
40
|
+
identifier,
|
|
41
|
+
(_: StableRecordIdentifier, bucket: NotificationType, notifiedKey?: string) => {
|
|
42
|
+
if (bucket === 'identity' || ((bucket === 'attributes' || bucket === 'property') && notifiedKey === 'id')) {
|
|
43
|
+
this._ref++;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
destroy() {
|
|
51
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
52
|
+
unsubscribe(this.#token);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
22
56
|
public get type(): string {
|
|
23
57
|
return this.identifier().type;
|
|
24
58
|
}
|
|
25
59
|
|
|
60
|
+
@cached
|
|
61
|
+
@dependentKeyCompat
|
|
26
62
|
private get _id(): string | null {
|
|
63
|
+
this._ref; // consume the tracked prop
|
|
27
64
|
let identifier = this.identifier();
|
|
28
65
|
if (identifier) {
|
|
29
66
|
return identifier.id;
|
|
@@ -51,7 +88,15 @@ export default class RecordReference extends Reference {
|
|
|
51
88
|
@return {String} The id of the record.
|
|
52
89
|
*/
|
|
53
90
|
id() {
|
|
54
|
-
|
|
91
|
+
if (CUSTOM_MODEL_CLASS) {
|
|
92
|
+
return this._id;
|
|
93
|
+
}
|
|
94
|
+
let identifier = this.identifier();
|
|
95
|
+
if (identifier) {
|
|
96
|
+
return identifier.id;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return null;
|
|
55
100
|
}
|
|
56
101
|
|
|
57
102
|
/**
|
|
@@ -93,7 +138,7 @@ export default class RecordReference extends Reference {
|
|
|
93
138
|
@public
|
|
94
139
|
@return {String} 'identity'
|
|
95
140
|
*/
|
|
96
|
-
remoteType(): '
|
|
141
|
+
remoteType(): 'identity' {
|
|
97
142
|
return 'identity';
|
|
98
143
|
}
|
|
99
144
|
|
|
@@ -160,7 +205,7 @@ export default class RecordReference extends Reference {
|
|
|
160
205
|
@return {Model} the record for this RecordReference
|
|
161
206
|
*/
|
|
162
207
|
value(): RecordInstance | null {
|
|
163
|
-
if (this.
|
|
208
|
+
if (this.id() !== null) {
|
|
164
209
|
let internalModel = internalModelForReference(this);
|
|
165
210
|
if (internalModel && internalModel.currentState.isLoaded) {
|
|
166
211
|
return internalModel.getRecord();
|
|
@@ -187,8 +232,9 @@ export default class RecordReference extends Reference {
|
|
|
187
232
|
@return {Promise<record>} the record for this RecordReference
|
|
188
233
|
*/
|
|
189
234
|
load() {
|
|
190
|
-
|
|
191
|
-
|
|
235
|
+
const id = this.id();
|
|
236
|
+
if (id !== null) {
|
|
237
|
+
return this.store.findRecord(this.type, id);
|
|
192
238
|
}
|
|
193
239
|
throw new Error(`Unable to fetch record of type ${this.type} without an id`);
|
|
194
240
|
}
|
|
@@ -211,8 +257,9 @@ export default class RecordReference extends Reference {
|
|
|
211
257
|
@return {Promise<record>} the record for this RecordReference
|
|
212
258
|
*/
|
|
213
259
|
reload() {
|
|
214
|
-
|
|
215
|
-
|
|
260
|
+
const id = this.id();
|
|
261
|
+
if (id !== null) {
|
|
262
|
+
return this.store.findRecord(this.type, id, { reload: true });
|
|
216
263
|
}
|
|
217
264
|
throw new Error(`Unable to fetch record of type ${this.type} without an id`);
|
|
218
265
|
}
|
|
@@ -100,7 +100,7 @@ abstract class Reference {
|
|
|
100
100
|
@public
|
|
101
101
|
@return {String} The name of the remote type. This should either be "link" or "ids"
|
|
102
102
|
*/
|
|
103
|
-
remoteType(): 'link' | 'id' | 'identity' {
|
|
103
|
+
remoteType(): 'link' | 'id' | 'ids' | 'identity' {
|
|
104
104
|
let value = this._resource();
|
|
105
105
|
if (isResourceIdentiferWithRelatedLinks(value)) {
|
|
106
106
|
return 'link';
|
package/index.js
CHANGED
|
@@ -10,6 +10,8 @@ module.exports = Object.assign({}, addonBaseConfig, {
|
|
|
10
10
|
shouldRollupPrivate: true,
|
|
11
11
|
externalDependenciesForPrivateModule() {
|
|
12
12
|
return [
|
|
13
|
+
'ember-cached-decorator-polyfill',
|
|
14
|
+
|
|
13
15
|
'@ember-data/canary-features',
|
|
14
16
|
'@ember-data/store/-debug',
|
|
15
17
|
|
|
@@ -23,6 +25,7 @@ module.exports = Object.assign({}, addonBaseConfig, {
|
|
|
23
25
|
'@ember/object/evented',
|
|
24
26
|
'@ember/object/internals',
|
|
25
27
|
'@ember/object/mixin',
|
|
28
|
+
'@ember/object/compat',
|
|
26
29
|
'@ember/object/promise-proxy-mixin',
|
|
27
30
|
'@ember/object/proxy',
|
|
28
31
|
'@ember/polyfills',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ember-data/store",
|
|
3
|
-
"version": "3.28.
|
|
3
|
+
"version": "3.28.11",
|
|
4
4
|
"description": "The default blueprint for ember-cli addons.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -17,16 +17,17 @@
|
|
|
17
17
|
"start": "ember serve"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@ember-data/canary-features": "3.28.
|
|
21
|
-
"@ember-data/private-build-infra": "3.28.
|
|
20
|
+
"@ember-data/canary-features": "3.28.11",
|
|
21
|
+
"@ember-data/private-build-infra": "3.28.11",
|
|
22
22
|
"@ember/string": "^3.0.0",
|
|
23
23
|
"@glimmer/tracking": "^1.0.4",
|
|
24
|
+
"ember-cached-decorator-polyfill": "^0.1.4",
|
|
24
25
|
"ember-cli-babel": "^7.26.6",
|
|
25
26
|
"ember-cli-path-utils": "^1.0.0",
|
|
26
27
|
"ember-cli-typescript": "^4.1.0"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"@ember-data/unpublished-test-infra": "3.28.
|
|
30
|
+
"@ember-data/unpublished-test-infra": "3.28.11",
|
|
30
31
|
"@ember/optional-features": "^2.0.0",
|
|
31
32
|
"@ember/test-helpers": "^2.2.5",
|
|
32
33
|
"@types/ember": "^3.16.5",
|