@ember-data/store 4.1.0-alpha.8 → 4.2.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.
- package/addon/-private/identifiers/cache.ts +3 -5
- package/addon/-private/identifiers/utils/uuid-v4.ts +0 -13
- package/addon/-private/index.ts +0 -1
- package/addon/-private/system/core-store.ts +25 -126
- package/addon/-private/system/ds-model-store.ts +2 -2
- package/addon/-private/system/fetch-manager.ts +10 -6
- package/addon/-private/system/model/internal-model.ts +42 -27
- package/addon/-private/system/model/states.js +7 -1
- package/addon/-private/system/record-array-manager.js +2 -3
- package/addon/-private/system/record-arrays/adapter-populated-record-array.js +2 -3
- package/addon/-private/system/record-notification-manager.ts +14 -6
- package/addon/-private/system/references/{belongs-to.js → belongs-to.ts} +95 -16
- package/addon/-private/system/references/{has-many.js → has-many.ts} +141 -45
- package/addon/-private/system/references/record.ts +52 -7
- package/addon/-private/system/references/reference.ts +4 -26
- package/addon/-private/system/request-cache.ts +6 -7
- package/addon/-private/system/snapshot.ts +1 -2
- package/addon/-private/system/store/finders.js +4 -11
- package/addon/-private/ts-interfaces/ds-model.ts +1 -0
- package/addon/-private/ts-interfaces/fetch-manager.ts +4 -0
- package/addon/-private/ts-interfaces/identifier.ts +2 -3
- package/index.js +3 -0
- package/package.json +10 -9
- package/addon/-private/utils/symbol.ts +0 -33
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
@module @ember-data/store
|
|
3
3
|
*/
|
|
4
4
|
import { assert, warn } from '@ember/debug';
|
|
5
|
-
import { assign } from '@ember/polyfills';
|
|
6
5
|
import { DEBUG } from '@glimmer/env';
|
|
7
6
|
|
|
8
7
|
import coerceId from '../system/coerce-id';
|
|
@@ -23,7 +22,6 @@ import type {
|
|
|
23
22
|
import { DEBUG_CLIENT_ORIGINATED, DEBUG_IDENTIFIER_BUCKET } from '../ts-interfaces/identifier';
|
|
24
23
|
import type { ConfidentDict } from '../ts-interfaces/utils';
|
|
25
24
|
import isNonEmptyString from '../utils/is-non-empty-string';
|
|
26
|
-
import { addSymbol } from '../utils/symbol';
|
|
27
25
|
import isStableIdentifier, { markStableIdentifier, unmarkStableIdentifier } from './is-stable-identifier';
|
|
28
26
|
import uuidv4 from './utils/uuid-v4';
|
|
29
27
|
|
|
@@ -372,7 +370,7 @@ export class IdentifierCache {
|
|
|
372
370
|
// If the incoming type does not match the identifier type, we need to create an identifier for the incoming
|
|
373
371
|
// data so we can merge the incoming data with the existing identifier, see #7325 and #7363
|
|
374
372
|
if ('type' in data && data.type && identifier.type !== normalizeModelName(data.type)) {
|
|
375
|
-
let incomingDataResource =
|
|
373
|
+
let incomingDataResource = { ...data };
|
|
376
374
|
// Need to strip the lid from the incomingData in order force a new identifier creation
|
|
377
375
|
delete incomingDataResource.lid;
|
|
378
376
|
existingIdentifier = this.getOrCreateRecordIdentifier(incomingDataResource);
|
|
@@ -511,8 +509,8 @@ function makeStableRecordIdentifier(
|
|
|
511
509
|
return `${clientOriginated ? '[CLIENT_ORIGINATED] ' : ''}${type}:${id} (${lid})`;
|
|
512
510
|
},
|
|
513
511
|
};
|
|
514
|
-
|
|
515
|
-
|
|
512
|
+
wrapper[DEBUG_CLIENT_ORIGINATED] = clientOriginated;
|
|
513
|
+
wrapper[DEBUG_IDENTIFIER_BUCKET] = bucket;
|
|
516
514
|
wrapper = freeze(wrapper);
|
|
517
515
|
markStableIdentifier(wrapper);
|
|
518
516
|
DEBUG_MAP.set(wrapper, recordIdentifier);
|
|
@@ -2,13 +2,6 @@
|
|
|
2
2
|
@module @ember-data/store
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
// support IE11
|
|
6
|
-
declare global {
|
|
7
|
-
interface Window {
|
|
8
|
-
msCrypto: Crypto;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
5
|
const CRYPTO = (() => {
|
|
13
6
|
const hasWindow = typeof window !== 'undefined';
|
|
14
7
|
const isFastBoot = typeof FastBoot !== 'undefined';
|
|
@@ -27,12 +20,6 @@ const CRYPTO = (() => {
|
|
|
27
20
|
};
|
|
28
21
|
} else if (hasWindow && typeof window.crypto !== 'undefined') {
|
|
29
22
|
return window.crypto;
|
|
30
|
-
} else if (
|
|
31
|
-
hasWindow &&
|
|
32
|
-
typeof window.msCrypto !== 'undefined' &&
|
|
33
|
-
typeof window.msCrypto.getRandomValues === 'function'
|
|
34
|
-
) {
|
|
35
|
-
return window.msCrypto;
|
|
36
23
|
} else {
|
|
37
24
|
throw new Error('ember-data: Cannot find a valid way to generate local identifiers');
|
|
38
25
|
}
|
package/addon/-private/index.ts
CHANGED
|
@@ -25,7 +25,6 @@ export { default as RootState } from './system/model/states';
|
|
|
25
25
|
export { default as InternalModel } from './system/model/internal-model';
|
|
26
26
|
|
|
27
27
|
export { PromiseArray, PromiseObject } from './system/promise-proxies';
|
|
28
|
-
export { addSymbol, symbol } from './utils/symbol';
|
|
29
28
|
|
|
30
29
|
export { RecordArray, AdapterPopulatedRecordArray } from './system/record-arrays';
|
|
31
30
|
|
|
@@ -5,7 +5,6 @@ import { getOwner } from '@ember/application';
|
|
|
5
5
|
import { A } from '@ember/array';
|
|
6
6
|
import { assert, deprecate, inspect, warn } from '@ember/debug';
|
|
7
7
|
import { computed, defineProperty, get, set } from '@ember/object';
|
|
8
|
-
import { assign } from '@ember/polyfills';
|
|
9
8
|
import { _backburner as emberBackburner } from '@ember/runloop';
|
|
10
9
|
import type { Backburner } from '@ember/runloop/-private/backburner';
|
|
11
10
|
import Service from '@ember/service';
|
|
@@ -31,7 +30,6 @@ import {
|
|
|
31
30
|
} from '@ember-data/private-build-infra';
|
|
32
31
|
import {
|
|
33
32
|
DEPRECATE_DEFAULT_ADAPTER,
|
|
34
|
-
DEPRECATE_DEFAULT_SERIALIZER,
|
|
35
33
|
DEPRECATE_LEGACY_TEST_REGISTRATIONS,
|
|
36
34
|
} from '@ember-data/private-build-infra/deprecations';
|
|
37
35
|
import type {
|
|
@@ -68,7 +66,6 @@ import type { FindOptions } from '../ts-interfaces/store';
|
|
|
68
66
|
import type { Dict } from '../ts-interfaces/utils';
|
|
69
67
|
import constructResource from '../utils/construct-resource';
|
|
70
68
|
import promiseRecord from '../utils/promise-record';
|
|
71
|
-
import { addSymbol } from '../utils/symbol';
|
|
72
69
|
import edBackburner from './backburner';
|
|
73
70
|
import coerceId, { ensureStringId } from './coerce-id';
|
|
74
71
|
import { errorsArrayToHash } from './errors-utils';
|
|
@@ -646,7 +643,7 @@ abstract class CoreStore extends Service {
|
|
|
646
643
|
return emberBackburner.join(() => {
|
|
647
644
|
return this._backburner.join(() => {
|
|
648
645
|
let normalizedModelName = normalizeModelName(modelName);
|
|
649
|
-
let properties =
|
|
646
|
+
let properties = { ...inputProperties };
|
|
650
647
|
|
|
651
648
|
// If the passed properties do not include a primary key,
|
|
652
649
|
// give the adapter an opportunity to generate one. Typically,
|
|
@@ -725,21 +722,6 @@ abstract class CoreStore extends Service {
|
|
|
725
722
|
if (internalModel) {
|
|
726
723
|
internalModel.deleteRecord();
|
|
727
724
|
}
|
|
728
|
-
} else {
|
|
729
|
-
deprecate(
|
|
730
|
-
`You passed a non ember-data managed record ${record} to store.deleteRecord. Ember Data store is not meant to manage non store records. This is not supported and will be removed`,
|
|
731
|
-
false,
|
|
732
|
-
{
|
|
733
|
-
id: 'ember-data:delete-record-non-store',
|
|
734
|
-
until: '4.0',
|
|
735
|
-
for: '@ember-data/store',
|
|
736
|
-
since: {
|
|
737
|
-
available: '3.28',
|
|
738
|
-
enabled: '3.28',
|
|
739
|
-
},
|
|
740
|
-
}
|
|
741
|
-
);
|
|
742
|
-
record.deleteRecord();
|
|
743
725
|
}
|
|
744
726
|
} else {
|
|
745
727
|
record.deleteRecord();
|
|
@@ -774,21 +756,6 @@ abstract class CoreStore extends Service {
|
|
|
774
756
|
if (internalModel) {
|
|
775
757
|
internalModel.unloadRecord();
|
|
776
758
|
}
|
|
777
|
-
} else {
|
|
778
|
-
deprecate(
|
|
779
|
-
`You passed a non ember-data managed record ${record} to store.unloadRecord. Ember Data store is not meant to manage non store records. This is not supported and will be removed`,
|
|
780
|
-
false,
|
|
781
|
-
{
|
|
782
|
-
id: 'ember-data:unload-record-non-store',
|
|
783
|
-
until: '4.0',
|
|
784
|
-
for: '@ember-data/store',
|
|
785
|
-
since: {
|
|
786
|
-
available: '3.28',
|
|
787
|
-
enabled: '3.28',
|
|
788
|
-
},
|
|
789
|
-
}
|
|
790
|
-
);
|
|
791
|
-
record.unloadRecord();
|
|
792
759
|
}
|
|
793
760
|
} else {
|
|
794
761
|
record.unloadRecord();
|
|
@@ -1280,7 +1247,7 @@ abstract class CoreStore extends Service {
|
|
|
1280
1247
|
return Promise.resolve(internalModel);
|
|
1281
1248
|
}
|
|
1282
1249
|
|
|
1283
|
-
_findByInternalModel(internalModel, options:
|
|
1250
|
+
_findByInternalModel(internalModel: InternalModel, options: FindOptions = {}) {
|
|
1284
1251
|
if (options.preload) {
|
|
1285
1252
|
this._backburner.join(() => {
|
|
1286
1253
|
internalModel.preloadData(options.preload);
|
|
@@ -1295,7 +1262,7 @@ abstract class CoreStore extends Service {
|
|
|
1295
1262
|
);
|
|
1296
1263
|
}
|
|
1297
1264
|
|
|
1298
|
-
_findEmptyInternalModel(internalModel, options) {
|
|
1265
|
+
_findEmptyInternalModel(internalModel: InternalModel, options: FindOptions) {
|
|
1299
1266
|
if (internalModel.currentState.isEmpty) {
|
|
1300
1267
|
return this._scheduleFetch(internalModel, options);
|
|
1301
1268
|
}
|
|
@@ -1307,9 +1274,9 @@ abstract class CoreStore extends Service {
|
|
|
1307
1274
|
}
|
|
1308
1275
|
} else {
|
|
1309
1276
|
if (internalModel.currentState.isLoading) {
|
|
1310
|
-
let
|
|
1311
|
-
if (
|
|
1312
|
-
return
|
|
1277
|
+
let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
|
|
1278
|
+
if (pendingRequest) {
|
|
1279
|
+
return pendingRequest.then(() => Promise.resolve(internalModel));
|
|
1313
1280
|
}
|
|
1314
1281
|
return this._scheduleFetch(internalModel, options);
|
|
1315
1282
|
}
|
|
@@ -1601,18 +1568,14 @@ abstract class CoreStore extends Service {
|
|
|
1601
1568
|
groups = [snapshots];
|
|
1602
1569
|
}
|
|
1603
1570
|
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
var group = groups[i];
|
|
1610
|
-
var totalInGroup = groups[i].length;
|
|
1611
|
-
var ids = new Array(totalInGroup);
|
|
1612
|
-
var groupedInternalModels = new Array(totalInGroup);
|
|
1571
|
+
for (let i = 0, l = groups.length; i < l; i++) {
|
|
1572
|
+
let group = groups[i];
|
|
1573
|
+
let totalInGroup = groups[i].length;
|
|
1574
|
+
let ids = new Array(totalInGroup);
|
|
1575
|
+
let groupedInternalModels = new Array(totalInGroup);
|
|
1613
1576
|
|
|
1614
|
-
for (
|
|
1615
|
-
|
|
1577
|
+
for (let j = 0; j < totalInGroup; j++) {
|
|
1578
|
+
let internalModel = group[j]._internalModel;
|
|
1616
1579
|
|
|
1617
1580
|
groupedInternalModels[j] = internalModel;
|
|
1618
1581
|
ids[j] = internalModel.id;
|
|
@@ -1629,7 +1592,7 @@ abstract class CoreStore extends Service {
|
|
|
1629
1592
|
});
|
|
1630
1593
|
})(groupedInternalModels);
|
|
1631
1594
|
} else if (ids.length === 1) {
|
|
1632
|
-
|
|
1595
|
+
let pair = seeking[groupedInternalModels[0].id];
|
|
1633
1596
|
_fetchRecord(pair);
|
|
1634
1597
|
} else {
|
|
1635
1598
|
assert("You cannot return an empty array from adapter's method groupRecordsForFindMany");
|
|
@@ -1765,7 +1728,7 @@ abstract class CoreStore extends Service {
|
|
|
1765
1728
|
if (arguments.length === 1 && isMaybeIdentifier(identifier)) {
|
|
1766
1729
|
let stableIdentifier = identifierCacheFor(this).peekRecordIdentifier(identifier);
|
|
1767
1730
|
if (stableIdentifier) {
|
|
1768
|
-
return internalModelFactoryFor(this).peek(stableIdentifier)?.getRecord();
|
|
1731
|
+
return internalModelFactoryFor(this).peek(stableIdentifier)?.getRecord() || null;
|
|
1769
1732
|
}
|
|
1770
1733
|
return null;
|
|
1771
1734
|
}
|
|
@@ -2055,7 +2018,7 @@ abstract class CoreStore extends Service {
|
|
|
2055
2018
|
if (internalModel) {
|
|
2056
2019
|
// short circuit if we are already loading
|
|
2057
2020
|
if (REQUEST_SERVICE) {
|
|
2058
|
-
let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier);
|
|
2021
|
+
let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
|
|
2059
2022
|
if (pendingRequest) {
|
|
2060
2023
|
return pendingRequest.then(() => internalModel.getRecord());
|
|
2061
2024
|
}
|
|
@@ -2087,6 +2050,10 @@ abstract class CoreStore extends Service {
|
|
|
2087
2050
|
return resolve(null);
|
|
2088
2051
|
}
|
|
2089
2052
|
|
|
2053
|
+
if (!internalModel) {
|
|
2054
|
+
assert(`No InternalModel found for ${resource.lid}`, internalModel);
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2090
2057
|
return this._findByInternalModel(internalModel, options);
|
|
2091
2058
|
}
|
|
2092
2059
|
|
|
@@ -2714,7 +2681,7 @@ abstract class CoreStore extends Service {
|
|
|
2714
2681
|
operation = 'deleteRecord';
|
|
2715
2682
|
}
|
|
2716
2683
|
|
|
2717
|
-
|
|
2684
|
+
options[SaveOp] = operation;
|
|
2718
2685
|
|
|
2719
2686
|
let fetchManagerPromise = this._fetchManager.scheduleSave(internalModel.identifier, options);
|
|
2720
2687
|
let promise = fetchManagerPromise.then(
|
|
@@ -3637,10 +3604,6 @@ abstract class CoreStore extends Service {
|
|
|
3637
3604
|
for an `App.ApplicationSerializer` (the default serializer for
|
|
3638
3605
|
your entire application).
|
|
3639
3606
|
|
|
3640
|
-
if no `App.ApplicationSerializer` is found, it will attempt
|
|
3641
|
-
to get the `defaultSerializer` from the `PersonAdapter`
|
|
3642
|
-
(`adapterFor('person')`).
|
|
3643
|
-
|
|
3644
3607
|
If a serializer cannot be found on the adapter, it will fall back
|
|
3645
3608
|
to an instance of `JSONSerializer`.
|
|
3646
3609
|
|
|
@@ -3708,31 +3671,6 @@ abstract class CoreStore extends Service {
|
|
|
3708
3671
|
}
|
|
3709
3672
|
|
|
3710
3673
|
let serializerName;
|
|
3711
|
-
if (DEPRECATE_DEFAULT_SERIALIZER) {
|
|
3712
|
-
// no model specific serializer or application serializer, check for the `defaultSerializer`
|
|
3713
|
-
// property defined on the adapter
|
|
3714
|
-
let adapter = this.adapterFor(modelName);
|
|
3715
|
-
serializerName = get(adapter, 'defaultSerializer');
|
|
3716
|
-
|
|
3717
|
-
deprecate(
|
|
3718
|
-
`store.serializerFor("${modelName}") resolved the "${serializerName}" serializer via the deprecated \`adapter.defaultSerializer\` property.\n\n\tPreviously, if no application or type-specific serializer was specified, the store would attempt to lookup a serializer via the \`defaultSerializer\` property on the type's adapter. This behavior is deprecated in favor of explicitly defining a type-specific serializer or application serializer`,
|
|
3719
|
-
!serializerName,
|
|
3720
|
-
{
|
|
3721
|
-
id: 'ember-data:default-serializer',
|
|
3722
|
-
until: '4.0',
|
|
3723
|
-
url: 'https://deprecations.emberjs.com/ember-data/v3.x/#toc_ember-data-default-serializers',
|
|
3724
|
-
for: '@ember-data/store',
|
|
3725
|
-
since: {
|
|
3726
|
-
available: '3.15',
|
|
3727
|
-
enabled: '3.15',
|
|
3728
|
-
},
|
|
3729
|
-
}
|
|
3730
|
-
);
|
|
3731
|
-
|
|
3732
|
-
serializer = serializerName
|
|
3733
|
-
? _serializerCache[serializerName] || owner.lookup(`serializer:${serializerName}`)
|
|
3734
|
-
: undefined;
|
|
3735
|
-
}
|
|
3736
3674
|
|
|
3737
3675
|
if (DEPRECATE_LEGACY_TEST_REGISTRATIONS) {
|
|
3738
3676
|
// in production this is handled by the re-export
|
|
@@ -3763,49 +3701,10 @@ abstract class CoreStore extends Service {
|
|
|
3763
3701
|
}
|
|
3764
3702
|
}
|
|
3765
3703
|
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE && serializer === undefined) {
|
|
3771
|
-
const JSONSerializer = require('@ember-data/serializer/json').default;
|
|
3772
|
-
owner.register('serializer:-default', JSONSerializer);
|
|
3773
|
-
serializer = owner.lookup('serializer:-default');
|
|
3774
|
-
|
|
3775
|
-
serializer && deprecateTestRegistration('serializer', '-default');
|
|
3776
|
-
}
|
|
3777
|
-
|
|
3778
|
-
deprecate(
|
|
3779
|
-
`store.serializerFor("${modelName}") resolved the "-default" serializer via the deprecated "-default" lookup fallback.\n\n\tPreviously, when no type-specific serializer, application serializer, or adapter.defaultSerializer had been defined by the app, the "-default" serializer would be used which defaulted to the \`JSONSerializer\`. This behavior is deprecated in favor of explicitly defining an application or type-specific serializer`,
|
|
3780
|
-
!serializer,
|
|
3781
|
-
{
|
|
3782
|
-
id: 'ember-data:default-serializer',
|
|
3783
|
-
until: '4.0',
|
|
3784
|
-
url: 'https://deprecations.emberjs.com/ember-data/v3.x/#toc_ember-data-default-serializers',
|
|
3785
|
-
for: '@ember-data/store',
|
|
3786
|
-
since: {
|
|
3787
|
-
available: '3.15',
|
|
3788
|
-
enabled: '3.15',
|
|
3789
|
-
},
|
|
3790
|
-
}
|
|
3791
|
-
);
|
|
3792
|
-
|
|
3793
|
-
assert(
|
|
3794
|
-
`No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
|
|
3795
|
-
serializer !== undefined
|
|
3796
|
-
);
|
|
3797
|
-
|
|
3798
|
-
set(serializer, 'store', this);
|
|
3799
|
-
_serializerCache[normalizedModelName] = serializer;
|
|
3800
|
-
_serializerCache['-default'] = serializer;
|
|
3801
|
-
|
|
3802
|
-
return serializer;
|
|
3803
|
-
} else {
|
|
3804
|
-
assert(
|
|
3805
|
-
`No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
|
|
3806
|
-
serializer !== undefined
|
|
3807
|
-
);
|
|
3808
|
-
}
|
|
3704
|
+
assert(
|
|
3705
|
+
`No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
|
|
3706
|
+
serializer !== undefined
|
|
3707
|
+
);
|
|
3809
3708
|
}
|
|
3810
3709
|
|
|
3811
3710
|
destroy() {
|
|
@@ -2,7 +2,6 @@ import { getOwner, setOwner } from '@ember/application';
|
|
|
2
2
|
import { assert, deprecate } from '@ember/debug';
|
|
3
3
|
import EmberError from '@ember/error';
|
|
4
4
|
import { get } from '@ember/object';
|
|
5
|
-
import { assign } from '@ember/polyfills';
|
|
6
5
|
import { isPresent } from '@ember/utils';
|
|
7
6
|
import { DEBUG } from '@glimmer/env';
|
|
8
7
|
|
|
@@ -38,9 +37,10 @@ class Store extends CoreStore {
|
|
|
38
37
|
let createOptions: any = {
|
|
39
38
|
store: this,
|
|
40
39
|
_internalModel: internalModel,
|
|
40
|
+
// TODO deprecate allowing unknown args setting
|
|
41
|
+
_createProps: createRecordArgs,
|
|
41
42
|
container: null,
|
|
42
43
|
};
|
|
43
|
-
assign(createOptions, createRecordArgs);
|
|
44
44
|
|
|
45
45
|
// ensure that `getOwner(this)` works inside a model instance
|
|
46
46
|
setOwner(createOptions, getOwner(this));
|
|
@@ -12,7 +12,6 @@ import type { CollectionResourceDocument, SingleResourceDocument } from '../ts-i
|
|
|
12
12
|
import type { FindRecordQuery, Request, SaveRecordMutation } from '../ts-interfaces/fetch-manager';
|
|
13
13
|
import type { ExistingRecordIdentifier, RecordIdentifier, StableRecordIdentifier } from '../ts-interfaces/identifier';
|
|
14
14
|
import type { Dict } from '../ts-interfaces/utils';
|
|
15
|
-
import { symbol } from '../utils/symbol';
|
|
16
15
|
import coerceId from './coerce-id';
|
|
17
16
|
import type CoreStore from './core-store';
|
|
18
17
|
import { errorsArrayToHash } from './errors-utils';
|
|
@@ -30,7 +29,7 @@ function payloadIsNotBlank(adapterPayload): boolean {
|
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
export const SaveOp: unique symbol =
|
|
32
|
+
export const SaveOp: unique symbol = Symbol('SaveOp');
|
|
34
33
|
|
|
35
34
|
interface PendingFetchItem {
|
|
36
35
|
identifier: ExistingRecordIdentifier;
|
|
@@ -502,10 +501,10 @@ export default class FetchManager {
|
|
|
502
501
|
}
|
|
503
502
|
}
|
|
504
503
|
|
|
505
|
-
getPendingFetch(identifier: StableRecordIdentifier) {
|
|
506
|
-
let pendingRequests = this.requestCache
|
|
507
|
-
.
|
|
508
|
-
|
|
504
|
+
getPendingFetch(identifier: StableRecordIdentifier, options) {
|
|
505
|
+
let pendingRequests = this.requestCache.getPendingRequestsForRecord(identifier).filter((req) => {
|
|
506
|
+
return req.type === 'query' && isSameRequest(options, req.request.data[0].options);
|
|
507
|
+
});
|
|
509
508
|
|
|
510
509
|
if (pendingRequests.length > 0) {
|
|
511
510
|
return pendingRequests[0][RequestPromise];
|
|
@@ -533,3 +532,8 @@ function assertIsString(id: string | null): asserts id is string {
|
|
|
533
532
|
}
|
|
534
533
|
}
|
|
535
534
|
}
|
|
535
|
+
|
|
536
|
+
// this function helps resolve whether we have a pending request that we should use instead
|
|
537
|
+
function isSameRequest(options: Dict<unknown> = {}, reqOptions: Dict<unknown> = {}) {
|
|
538
|
+
return options.include === reqOptions.include;
|
|
539
|
+
}
|
|
@@ -3,7 +3,6 @@ import { A, default as EmberArray } from '@ember/array';
|
|
|
3
3
|
import { assert, inspect } from '@ember/debug';
|
|
4
4
|
import EmberError from '@ember/error';
|
|
5
5
|
import { get, set } from '@ember/object';
|
|
6
|
-
import { assign } from '@ember/polyfills';
|
|
7
6
|
import { _backburner as emberBackburner, cancel, run } from '@ember/runloop';
|
|
8
7
|
import { DEBUG } from '@glimmer/env';
|
|
9
8
|
|
|
@@ -25,6 +24,7 @@ import type {
|
|
|
25
24
|
import type { UpgradedMeta } from '@ember-data/record-data/-private/graph/-edge-definition';
|
|
26
25
|
|
|
27
26
|
import { identifierCacheFor } from '../../identifiers/cache';
|
|
27
|
+
import { DSModel } from '../../ts-interfaces/ds-model';
|
|
28
28
|
import type { StableRecordIdentifier } from '../../ts-interfaces/identifier';
|
|
29
29
|
import type { RecordData } from '../../ts-interfaces/record-data';
|
|
30
30
|
import type { JsonApiResource, JsonApiValidationError } from '../../ts-interfaces/record-data-json-api';
|
|
@@ -128,7 +128,7 @@ export default class InternalModel {
|
|
|
128
128
|
declare _deferredTriggers: any;
|
|
129
129
|
declare __recordArrays: any;
|
|
130
130
|
declare references: any;
|
|
131
|
-
declare _recordReference:
|
|
131
|
+
declare _recordReference: RecordReference;
|
|
132
132
|
declare _manyArrayCache: ConfidentDict<ManyArray>;
|
|
133
133
|
|
|
134
134
|
declare _relationshipPromisesCache: ConfidentDict<RSVP.Promise<any>>;
|
|
@@ -200,7 +200,7 @@ export default class InternalModel {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
get recordReference() {
|
|
203
|
+
get recordReference(): RecordReference {
|
|
204
204
|
if (this._recordReference === null) {
|
|
205
205
|
this._recordReference = new RecordReference(this.store, this.identifier);
|
|
206
206
|
}
|
|
@@ -292,7 +292,7 @@ export default class InternalModel {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
getRecord(properties?) {
|
|
295
|
+
getRecord(properties?): Object {
|
|
296
296
|
if (!this._record && !this._isDematerializing) {
|
|
297
297
|
let { store } = this;
|
|
298
298
|
|
|
@@ -354,7 +354,7 @@ export default class InternalModel {
|
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
let additionalCreateOptions = this._recordData._initRecordCreateOptions(properties);
|
|
357
|
-
assign(createOptions, additionalCreateOptions);
|
|
357
|
+
Object.assign(createOptions, additionalCreateOptions);
|
|
358
358
|
|
|
359
359
|
// ensure that `getOwner(this)` works inside a model instance
|
|
360
360
|
setOwner(createOptions, getOwner(store));
|
|
@@ -614,7 +614,7 @@ export default class InternalModel {
|
|
|
614
614
|
"' with id " +
|
|
615
615
|
parentInternalModel.id +
|
|
616
616
|
' 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 })`)',
|
|
617
|
-
toReturn === null || !toReturn.
|
|
617
|
+
toReturn === null || !(toReturn as DSModel).isEmpty
|
|
618
618
|
);
|
|
619
619
|
return toReturn;
|
|
620
620
|
}
|
|
@@ -673,7 +673,7 @@ export default class InternalModel {
|
|
|
673
673
|
assert(`hasMany only works with the @ember-data/record-data package`);
|
|
674
674
|
}
|
|
675
675
|
|
|
676
|
-
getHasMany(key: string, options) {
|
|
676
|
+
getHasMany(key: string, options?) {
|
|
677
677
|
if (HAS_RECORD_DATA_PACKAGE) {
|
|
678
678
|
const graphFor = require('@ember-data/record-data/-private').graphFor;
|
|
679
679
|
const relationship = graphFor(this.store).get(this.identifier, key);
|
|
@@ -791,11 +791,22 @@ export default class InternalModel {
|
|
|
791
791
|
!this._record || this._record.get('isDestroyed') || this._record.get('isDestroying')
|
|
792
792
|
);
|
|
793
793
|
this.isDestroying = true;
|
|
794
|
+
if (this._recordReference) {
|
|
795
|
+
this._recordReference.destroy();
|
|
796
|
+
}
|
|
797
|
+
this._recordReference = null;
|
|
794
798
|
let cache = this._manyArrayCache;
|
|
795
799
|
Object.keys(cache).forEach((key) => {
|
|
796
800
|
cache[key].destroy();
|
|
797
801
|
delete cache[key];
|
|
798
802
|
});
|
|
803
|
+
if (this.references) {
|
|
804
|
+
cache = this.references;
|
|
805
|
+
Object.keys(cache).forEach((key) => {
|
|
806
|
+
cache[key].destroy();
|
|
807
|
+
delete cache[key];
|
|
808
|
+
});
|
|
809
|
+
}
|
|
799
810
|
|
|
800
811
|
internalModelFactoryFor(this.store).remove(this);
|
|
801
812
|
this._isDestroyed = true;
|
|
@@ -804,6 +815,7 @@ export default class InternalModel {
|
|
|
804
815
|
setupData(data) {
|
|
805
816
|
let changedKeys = this._recordData.pushData(data, this.hasRecord);
|
|
806
817
|
if (this.hasRecord) {
|
|
818
|
+
// TODO @runspired should this be going through the notification manager?
|
|
807
819
|
this._record._notifyProperties(changedKeys);
|
|
808
820
|
}
|
|
809
821
|
this.send('pushedData');
|
|
@@ -903,11 +915,18 @@ export default class InternalModel {
|
|
|
903
915
|
|
|
904
916
|
notifyHasManyChange(key: string) {
|
|
905
917
|
if (this.hasRecord) {
|
|
918
|
+
let manyArray = this._manyArrayCache[key];
|
|
919
|
+
let hasPromise = !!this._relationshipPromisesCache[key];
|
|
920
|
+
|
|
921
|
+
if (manyArray && hasPromise) {
|
|
922
|
+
// do nothing, we will notify the ManyArray directly
|
|
923
|
+
// once the fetch has completed.
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
|
|
906
927
|
if (CUSTOM_MODEL_CLASS) {
|
|
907
928
|
this.store._notificationManager.notify(this.identifier, 'relationships', key);
|
|
908
929
|
} else {
|
|
909
|
-
let manyArray = this._manyArrayCache[key];
|
|
910
|
-
|
|
911
930
|
if (manyArray) {
|
|
912
931
|
manyArray.notify();
|
|
913
932
|
|
|
@@ -957,10 +976,10 @@ export default class InternalModel {
|
|
|
957
976
|
this.store._notificationManager.notify(this.identifier, 'state');
|
|
958
977
|
} else {
|
|
959
978
|
if (!key || key === 'isNew') {
|
|
960
|
-
this.getRecord().notifyPropertyChange('isNew');
|
|
979
|
+
(this.getRecord() as DSModel).notifyPropertyChange('isNew');
|
|
961
980
|
}
|
|
962
981
|
if (!key || key === 'isDeleted') {
|
|
963
|
-
this.getRecord().notifyPropertyChange('isDeleted');
|
|
982
|
+
(this.getRecord() as DSModel).notifyPropertyChange('isDeleted');
|
|
964
983
|
}
|
|
965
984
|
}
|
|
966
985
|
}
|
|
@@ -1264,12 +1283,12 @@ export default class InternalModel {
|
|
|
1264
1283
|
if (this._recordData.getErrors) {
|
|
1265
1284
|
return this._recordData.getErrors(this.identifier).length > 0;
|
|
1266
1285
|
} else {
|
|
1267
|
-
let errors =
|
|
1268
|
-
return errors.
|
|
1286
|
+
let errors = (this.getRecord() as DSModel).errors;
|
|
1287
|
+
return errors.length > 0;
|
|
1269
1288
|
}
|
|
1270
1289
|
} else {
|
|
1271
|
-
let errors =
|
|
1272
|
-
return errors.
|
|
1290
|
+
let errors = (this.getRecord() as DSModel).errors;
|
|
1291
|
+
return errors.length > 0;
|
|
1273
1292
|
}
|
|
1274
1293
|
}
|
|
1275
1294
|
|
|
@@ -1284,7 +1303,7 @@ export default class InternalModel {
|
|
|
1284
1303
|
if (!this._recordData.getErrors) {
|
|
1285
1304
|
for (attribute in parsedErrors) {
|
|
1286
1305
|
if (hasOwnProperty.call(parsedErrors, attribute)) {
|
|
1287
|
-
this.getRecord().errors._add(attribute, parsedErrors[attribute]);
|
|
1306
|
+
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1288
1307
|
}
|
|
1289
1308
|
}
|
|
1290
1309
|
}
|
|
@@ -1304,7 +1323,7 @@ export default class InternalModel {
|
|
|
1304
1323
|
|
|
1305
1324
|
for (attribute in parsedErrors) {
|
|
1306
1325
|
if (hasOwnProperty.call(parsedErrors, attribute)) {
|
|
1307
|
-
this.getRecord().errors._add(attribute, parsedErrors[attribute]);
|
|
1326
|
+
(this.getRecord() as DSModel).errors._add(attribute, parsedErrors[attribute]);
|
|
1308
1327
|
}
|
|
1309
1328
|
}
|
|
1310
1329
|
|
|
@@ -1456,15 +1475,11 @@ export function extractRecordDataFromRecord(recordOrPromiseRecord) {
|
|
|
1456
1475
|
}
|
|
1457
1476
|
|
|
1458
1477
|
function anyUnloaded(store: CoreStore, relationship: ManyRelationship) {
|
|
1459
|
-
// Can't use `find` because of IE11 and these arrays are potentially massive
|
|
1460
1478
|
let state = relationship.currentState;
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
return unloaded;
|
|
1479
|
+
const unloaded = state.find((s) => {
|
|
1480
|
+
let im = store._internalModelForResource(s);
|
|
1481
|
+
return im._isDematerializing || !im.currentState.isLoaded;
|
|
1482
|
+
});
|
|
1483
|
+
|
|
1484
|
+
return unloaded || false;
|
|
1470
1485
|
}
|
|
@@ -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
|
};
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import { A } from '@ember/array';
|
|
6
6
|
import { assert } from '@ember/debug';
|
|
7
7
|
import { get, set } from '@ember/object';
|
|
8
|
-
import { assign } from '@ember/polyfills';
|
|
9
8
|
import { _backburner as emberBackburner } from '@ember/runloop';
|
|
10
9
|
|
|
11
10
|
import { REMOVE_RECORD_ARRAY_MANAGER_LEGACY_COMPAT } from '@ember-data/canary-features';
|
|
@@ -281,8 +280,8 @@ class RecordArrayManager {
|
|
|
281
280
|
manager: this,
|
|
282
281
|
isLoaded: true,
|
|
283
282
|
isUpdating: false,
|
|
284
|
-
meta:
|
|
285
|
-
links:
|
|
283
|
+
meta: { ...payload.meta },
|
|
284
|
+
links: { ...payload.links },
|
|
286
285
|
});
|
|
287
286
|
|
|
288
287
|
this._associateWithRecordArray(identifiers, array);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { A } from '@ember/array';
|
|
2
2
|
import { get } from '@ember/object';
|
|
3
|
-
import { assign } from '@ember/polyfills';
|
|
4
3
|
import { once } from '@ember/runloop';
|
|
5
4
|
import { DEBUG } from '@glimmer/env';
|
|
6
5
|
|
|
@@ -86,8 +85,8 @@ let AdapterPopulatedRecordArray = RecordArray.extend({
|
|
|
86
85
|
this.setProperties({
|
|
87
86
|
isLoaded: true,
|
|
88
87
|
isUpdating: false,
|
|
89
|
-
meta:
|
|
90
|
-
links:
|
|
88
|
+
meta: { ...payload.meta },
|
|
89
|
+
links: { ...payload.links },
|
|
91
90
|
});
|
|
92
91
|
|
|
93
92
|
this.manager._associateWithRecordArray(identifiersOrInternalModels, this);
|