@ember-data/store 4.4.0-alpha.9 → 4.4.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.
Files changed (33) hide show
  1. package/addon/-private/system/core-store.ts +147 -134
  2. package/addon/-private/system/ds-model-store.ts +10 -1
  3. package/addon/-private/system/fetch-manager.ts +21 -48
  4. package/addon/-private/system/model/internal-model.ts +192 -263
  5. package/addon/-private/system/model/states.js +41 -5
  6. package/addon/-private/system/{promise-proxies.ts → promise-proxies.js} +21 -31
  7. package/addon/-private/system/{record-array-manager.ts → record-array-manager.js} +60 -87
  8. package/addon/-private/system/record-arrays/adapter-populated-record-array.js +95 -0
  9. package/addon/-private/system/record-arrays/{record-array.ts → record-array.js} +75 -96
  10. package/addon/-private/system/record-data-for.ts +0 -2
  11. package/addon/-private/system/references/belongs-to.ts +2 -3
  12. package/addon/-private/system/references/has-many.ts +2 -4
  13. package/addon/-private/system/schema-definition-service.ts +2 -2
  14. package/addon/-private/system/snapshot-record-array.ts +11 -12
  15. package/addon/-private/system/snapshot.ts +7 -24
  16. package/addon/-private/system/store/common.js +1 -24
  17. package/addon/-private/system/store/finders.js +5 -53
  18. package/addon/-private/system/store/internal-model-factory.ts +7 -8
  19. package/addon/-private/system/store/record-data-store-wrapper.ts +2 -7
  20. package/addon/-private/system/store/serializer-response.js +71 -0
  21. package/addon/-private/ts-interfaces/ds-model.ts +7 -15
  22. package/addon/-private/ts-interfaces/ember-data-json-api.ts +0 -3
  23. package/addon/-private/ts-interfaces/minimum-adapter-interface.ts +20 -19
  24. package/addon/-private/ts-interfaces/minimum-serializer-interface.ts +6 -27
  25. package/addon/-private/ts-interfaces/record-data.ts +1 -4
  26. package/addon/-private/ts-interfaces/record-instance.ts +1 -3
  27. package/addon/-private/ts-interfaces/store.ts +0 -1
  28. package/addon/-private/utils/promise-record.ts +3 -3
  29. package/index.js +0 -3
  30. package/package.json +6 -7
  31. package/addon/-private/system/promise-proxy-base.js +0 -7
  32. package/addon/-private/system/record-arrays/adapter-populated-record-array.ts +0 -129
  33. package/addon/-private/system/store/serializer-response.ts +0 -85
@@ -13,14 +13,19 @@ import { isNone, isPresent, typeOf } from '@ember/utils';
13
13
  import { DEBUG } from '@glimmer/env';
14
14
  import Ember from 'ember';
15
15
 
16
- import { importSync } from '@embroider/macros';
17
- import { all, default as RSVP, resolve } from 'rsvp';
16
+ import require from 'require';
17
+ import { all, default as RSVP, Promise, resolve } from 'rsvp';
18
18
 
19
19
  import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
20
- import type { ManyRelationship, RecordData as RecordDataClass } from '@ember-data/record-data/-private';
20
+ import type {
21
+ BelongsToRelationship,
22
+ ManyRelationship,
23
+ RecordData as RecordDataClass,
24
+ } from '@ember-data/record-data/-private';
21
25
  import type { RelationshipState } from '@ember-data/record-data/-private/graph/-state';
22
26
 
23
27
  import { IdentifierCache } from '../identifiers/cache';
28
+ import type { DSModel } from '../ts-interfaces/ds-model';
24
29
  import type {
25
30
  CollectionResourceDocument,
26
31
  EmptyResourceDocument,
@@ -34,12 +39,11 @@ import type {
34
39
  StableExistingRecordIdentifier,
35
40
  StableRecordIdentifier,
36
41
  } from '../ts-interfaces/identifier';
37
- import { MinimumAdapterInterface } from '../ts-interfaces/minimum-adapter-interface';
38
- import type { MinimumSerializerInterface } from '../ts-interfaces/minimum-serializer-interface';
42
+ import type { PromiseProxy } from '../ts-interfaces/promise-proxies';
39
43
  import type { RecordData } from '../ts-interfaces/record-data';
40
44
  import type { JsonApiRelationship } from '../ts-interfaces/record-data-json-api';
41
45
  import type { RecordDataRecordWrapper } from '../ts-interfaces/record-data-record-wrapper';
42
- import type { AttributesSchema, RelationshipsSchema } from '../ts-interfaces/record-data-schemas';
46
+ import type { AttributesSchema } from '../ts-interfaces/record-data-schemas';
43
47
  import type { RecordInstance } from '../ts-interfaces/record-instance';
44
48
  import type { SchemaDefinitionService } from '../ts-interfaces/schema-definition-service';
45
49
  import type { FindOptions } from '../ts-interfaces/store';
@@ -58,10 +62,8 @@ import {
58
62
  import type ShimModelClass from './model/shim-model-class';
59
63
  import { getShimClass } from './model/shim-model-class';
60
64
  import normalizeModelName from './normalize-model-name';
61
- import type { PromiseArray, PromiseObject } from './promise-proxies';
62
65
  import { promiseArray, promiseObject } from './promise-proxies';
63
66
  import RecordArrayManager from './record-array-manager';
64
- import { AdapterPopulatedRecordArray, RecordArray } from './record-arrays';
65
67
  import { setRecordDataFor } from './record-data-for';
66
68
  import NotificationManager from './record-notification-manager';
67
69
  import type { BelongsToReference, HasManyReference } from './references';
@@ -82,6 +84,7 @@ let _RecordData: RecordDataConstruct | undefined;
82
84
 
83
85
  const { ENV } = Ember;
84
86
  type AsyncTrackingToken = Readonly<{ label: string; trace: Error | string }>;
87
+ type PromiseArray<T> = Promise<T[]>;
85
88
 
86
89
  const RECORD_REFERENCES = new WeakCache<StableRecordIdentifier, RecordReference>(DEBUG ? 'reference' : '');
87
90
 
@@ -93,11 +96,6 @@ function freeze<T>(obj: T): T {
93
96
  return obj;
94
97
  }
95
98
 
96
- export interface CreateRecordProperties {
97
- id?: string | null;
98
- [key: string]: unknown;
99
- }
100
-
101
99
  /**
102
100
  The store contains all of the data for records loaded from the server.
103
101
  It is also responsible for creating instances of `Model` that wrap
@@ -174,31 +172,36 @@ export interface CreateRecordProperties {
174
172
 
175
173
  abstract class CoreStore extends Service {
176
174
  /**
177
- * Ember Data uses several specialized micro-queues for organizing
178
- and coalescing similar async work.
179
-
180
- These queues are currently controlled by a flush scheduled into
181
- ember-data's custom backburner instance.
182
- *
183
175
  * EmberData specific backburner instance
184
176
  * @property _backburner
185
177
  * @private
186
178
  */
187
- declare _backburner: Backburner;
188
- declare recordArrayManager: RecordArrayManager;
179
+ public _backburner: Backburner = edBackburner;
180
+ public recordArrayManager: RecordArrayManager = new RecordArrayManager({ store: this });
189
181
 
190
182
  declare _notificationManager: NotificationManager;
191
183
  declare identifierCache: IdentifierCache;
192
- declare _adapterCache: Dict<MinimumAdapterInterface & { store: CoreStore }>;
193
- declare _serializerCache: Dict<MinimumSerializerInterface & { store: CoreStore }>;
194
- declare _storeWrapper: RecordDataStoreWrapper;
184
+ private _adapterCache = Object.create(null);
185
+ private _serializerCache = Object.create(null);
186
+ public _storeWrapper = new RecordDataStoreWrapper(this);
187
+
188
+ /*
189
+ Ember Data uses several specialized micro-queues for organizing
190
+ and coalescing similar async work.
191
+
192
+ These queues are currently controlled by a flush scheduled into
193
+ ember-data's custom backburner instance.
194
+ */
195
+ // used for coalescing internal model updates
196
+ private _updatedInternalModels: InternalModel[] = [];
197
+
195
198
  declare _fetchManager: FetchManager;
196
199
  declare _schemaDefinitionService: SchemaDefinitionService;
197
200
 
198
201
  // DEBUG-only properties
199
202
  declare _trackedAsyncRequests: AsyncTrackingToken[];
200
- declare shouldTrackAsyncRequests: boolean;
201
- declare generateStackTracesForTrackedRequests: boolean;
203
+ shouldTrackAsyncRequests: boolean = false;
204
+ generateStackTracesForTrackedRequests: boolean = false;
202
205
  declare _trackAsyncRequestStart: (str: string) => void;
203
206
  declare _trackAsyncRequestEnd: (token: AsyncTrackingToken) => void;
204
207
  declare __asyncWaiter: () => boolean;
@@ -249,11 +252,6 @@ abstract class CoreStore extends Service {
249
252
  */
250
253
  constructor() {
251
254
  super(...arguments);
252
- this._adapterCache = Object.create(null);
253
- this._serializerCache = Object.create(null);
254
- this._storeWrapper = new RecordDataStoreWrapper(this);
255
- this._backburner = edBackburner;
256
- this.recordArrayManager = new RecordArrayManager({ store: this });
257
255
 
258
256
  RECORD_REFERENCES._generator = (identifier) => {
259
257
  return new RecordReference(this, identifier);
@@ -392,14 +390,19 @@ abstract class CoreStore extends Service {
392
390
  recordDataFor: (identifier: RecordIdentifier) => RecordDataRecordWrapper,
393
391
  notificationManager: NotificationManager
394
392
  ): RecordInstance;
393
+
395
394
  abstract teardownRecord(record: RecordInstance): void;
396
- abstract getSchemaDefinitionService(): SchemaDefinitionService;
397
395
 
396
+ _internalDeleteRecord(internalModel: InternalModel) {
397
+ internalModel.deleteRecord();
398
+ }
399
+
400
+ // FeatureFlagged in the DSModelStore claas
398
401
  _attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
399
402
  return this.getSchemaDefinitionService().attributesDefinitionFor(identifier);
400
403
  }
401
404
 
402
- _relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
405
+ _relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }) {
403
406
  return this.getSchemaDefinitionService().relationshipsDefinitionFor(identifier);
404
407
  }
405
408
 
@@ -407,6 +410,11 @@ abstract class CoreStore extends Service {
407
410
  this._schemaDefinitionService = schema;
408
411
  }
409
412
 
413
+ getSchemaDefinitionService(): SchemaDefinitionService {
414
+ return this._schemaDefinitionService;
415
+ }
416
+
417
+ // TODO Double check this return value is correct
410
418
  _relationshipMetaFor(modelName: string, id: string | null, key: string) {
411
419
  return this._relationshipsDefinitionFor({ type: modelName })[key];
412
420
  }
@@ -491,7 +499,7 @@ abstract class CoreStore extends Service {
491
499
  newly created record.
492
500
  @return {Model} record
493
501
  */
494
- createRecord(modelName: string, inputProperties: CreateRecordProperties): RecordInstance {
502
+ createRecord(modelName, inputProperties) {
495
503
  if (DEBUG) {
496
504
  assertDestroyingStore(this, 'createRecord');
497
505
  }
@@ -545,7 +553,7 @@ abstract class CoreStore extends Service {
545
553
  @param {Object} properties from the new record
546
554
  @return {String} if the adapter can generate one, an ID
547
555
  */
548
- _generateId(modelName: string, properties: CreateRecordProperties): string | null {
556
+ _generateId(modelName, properties) {
549
557
  let adapter = this.adapterFor(modelName);
550
558
 
551
559
  if (adapter && adapter.generateIdForRecord) {
@@ -576,7 +584,7 @@ abstract class CoreStore extends Service {
576
584
  @public
577
585
  @param {Model} record
578
586
  */
579
- deleteRecord(record: RecordInstance): void {
587
+ deleteRecord(record) {
580
588
  if (DEBUG) {
581
589
  assertDestroyingStore(this, 'deleteRecord');
582
590
  }
@@ -607,7 +615,7 @@ abstract class CoreStore extends Service {
607
615
  @public
608
616
  @param {Model} record
609
617
  */
610
- unloadRecord(record: RecordInstance): void {
618
+ unloadRecord(record) {
611
619
  if (DEBUG) {
612
620
  assertDestroyingStore(this, 'unloadRecord');
613
621
  }
@@ -632,7 +640,7 @@ abstract class CoreStore extends Service {
632
640
  @return {Promise} promise
633
641
  @private
634
642
  */
635
- find(modelName: string, id: string | number, options?): PromiseObject<RecordInstance> {
643
+ find(modelName, id, options) {
636
644
  if (DEBUG) {
637
645
  assertDestroyingStore(this, 'find');
638
646
  }
@@ -1031,13 +1039,13 @@ abstract class CoreStore extends Service {
1031
1039
  @param {Object} [options] - if the first param is a string this will be the optional options for the request. See examples for available options.
1032
1040
  @return {Promise} promise
1033
1041
  */
1034
- findRecord(resource: string, id: string | number, options?: FindOptions): PromiseObject<RecordInstance>;
1035
- findRecord(resource: ResourceIdentifierObject, id?: FindOptions): PromiseObject<RecordInstance>;
1042
+ findRecord(resource: string, id: string | number, options?: FindOptions): PromiseProxy<DSModel>;
1043
+ findRecord(resource: ResourceIdentifierObject, id?: FindOptions): PromiseProxy<DSModel>;
1036
1044
  findRecord(
1037
1045
  resource: string | ResourceIdentifierObject,
1038
1046
  id?: string | number | FindOptions,
1039
1047
  options?: FindOptions
1040
- ): PromiseObject<RecordInstance> {
1048
+ ): PromiseProxy<DSModel> {
1041
1049
  if (DEBUG) {
1042
1050
  assertDestroyingStore(this, 'findRecord');
1043
1051
  }
@@ -1062,10 +1070,7 @@ abstract class CoreStore extends Service {
1062
1070
  options = options || {};
1063
1071
 
1064
1072
  if (!internalModel.currentState.isLoaded) {
1065
- return promiseRecord(
1066
- this._findByInternalModel(internalModel, options),
1067
- `DS: Store#findRecord ${internalModel.identifier}`
1068
- );
1073
+ return this._findByInternalModel(internalModel, options);
1069
1074
  }
1070
1075
 
1071
1076
  let fetchedInternalModel = this._findRecord(internalModel, options);
@@ -1073,7 +1078,7 @@ abstract class CoreStore extends Service {
1073
1078
  return promiseRecord(fetchedInternalModel, `DS: Store#findRecord ${internalModel.identifier}`);
1074
1079
  }
1075
1080
 
1076
- _findRecord(internalModel: InternalModel, options: FindOptions): Promise<InternalModel> {
1081
+ _findRecord(internalModel: InternalModel, options: FindOptions) {
1077
1082
  // Refetch if the reload option is passed
1078
1083
  if (options.reload) {
1079
1084
  return this._scheduleFetch(internalModel, options);
@@ -1092,7 +1097,7 @@ abstract class CoreStore extends Service {
1092
1097
  }
1093
1098
 
1094
1099
  if (options.backgroundReload === false) {
1095
- return resolve(internalModel);
1100
+ return Promise.resolve(internalModel);
1096
1101
  }
1097
1102
 
1098
1103
  // Trigger the background refetch if backgroundReload option is passed
@@ -1105,20 +1110,25 @@ abstract class CoreStore extends Service {
1105
1110
  }
1106
1111
 
1107
1112
  // Return the cached record
1108
- return resolve(internalModel);
1113
+ return Promise.resolve(internalModel);
1109
1114
  }
1110
1115
 
1111
- _findByInternalModel(internalModel: InternalModel, options: FindOptions = {}): Promise<InternalModel> {
1116
+ _findByInternalModel(internalModel: InternalModel, options: FindOptions = {}) {
1112
1117
  if (options.preload) {
1113
1118
  this._backburner.join(() => {
1114
1119
  internalModel.preloadData(options.preload);
1115
1120
  });
1116
1121
  }
1117
1122
 
1118
- return this._findEmptyInternalModel(internalModel, options);
1123
+ let fetchedInternalModel = this._findEmptyInternalModel(internalModel, options);
1124
+
1125
+ return promiseRecord(
1126
+ fetchedInternalModel,
1127
+ `DS: Store#findRecord ${internalModel.modelName} with id: ${internalModel.id}`
1128
+ );
1119
1129
  }
1120
1130
 
1121
- _findEmptyInternalModel(internalModel: InternalModel, options: FindOptions): Promise<InternalModel> {
1131
+ _findEmptyInternalModel(internalModel: InternalModel, options: FindOptions) {
1122
1132
  if (internalModel.currentState.isEmpty) {
1123
1133
  return this._scheduleFetch(internalModel, options);
1124
1134
  }
@@ -1126,12 +1136,12 @@ abstract class CoreStore extends Service {
1126
1136
  if (internalModel.currentState.isLoading) {
1127
1137
  let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
1128
1138
  if (pendingRequest) {
1129
- return pendingRequest.then(() => resolve(internalModel));
1139
+ return pendingRequest.then(() => Promise.resolve(internalModel));
1130
1140
  }
1131
1141
  return this._scheduleFetch(internalModel, options);
1132
1142
  }
1133
1143
 
1134
- return resolve(internalModel);
1144
+ return Promise.resolve(internalModel);
1135
1145
  }
1136
1146
 
1137
1147
  /**
@@ -1172,10 +1182,10 @@ abstract class CoreStore extends Service {
1172
1182
  fetches[i] = this._scheduleFetch(internalModels[i], options);
1173
1183
  }
1174
1184
 
1175
- return all(fetches);
1185
+ return Promise.all(fetches);
1176
1186
  }
1177
1187
 
1178
- _scheduleFetch(internalModel: InternalModel, options = {}): Promise<InternalModel> {
1188
+ _scheduleFetch(internalModel: InternalModel, options = {}): RSVP.Promise<InternalModel> {
1179
1189
  let generateStackTrace = this.generateStackTracesForTrackedRequests;
1180
1190
  // TODO remove this once we don't rely on state machine
1181
1191
  internalModel.send('loadingData');
@@ -1366,7 +1376,7 @@ abstract class CoreStore extends Service {
1366
1376
  @param options optional to include adapterOptions
1367
1377
  @return {Promise} promise
1368
1378
  */
1369
- _reloadRecord(internalModel: InternalModel, options: FindOptions): Promise<InternalModel> {
1379
+ _reloadRecord(internalModel, options): RSVP.Promise<InternalModel> {
1370
1380
  options.isReloading = true;
1371
1381
  let { id, modelName } = internalModel;
1372
1382
  let adapter = this.adapterFor(modelName);
@@ -1375,7 +1385,7 @@ abstract class CoreStore extends Service {
1375
1385
  assert(`You tried to reload a record but you have no adapter (for ${modelName})`, adapter);
1376
1386
  assert(
1377
1387
  `You tried to reload a record but your adapter does not implement 'findRecord'`,
1378
- typeof adapter.findRecord === 'function'
1388
+ typeof adapter.findRecord === 'function' || typeof adapter.find === 'function'
1379
1389
  );
1380
1390
 
1381
1391
  return this._scheduleFetch(internalModel, options);
@@ -1462,7 +1472,7 @@ abstract class CoreStore extends Service {
1462
1472
  finds[i] = this._findEmptyInternalModel(internalModels[i], options);
1463
1473
  }
1464
1474
 
1465
- return all(finds);
1475
+ return Promise.all(finds);
1466
1476
  }
1467
1477
 
1468
1478
  /**
@@ -1504,12 +1514,12 @@ abstract class CoreStore extends Service {
1504
1514
  _findHasManyByJsonApiResource(
1505
1515
  resource,
1506
1516
  parentInternalModel: InternalModel,
1507
- relationship: ManyRelationship,
1508
- options?: Dict<unknown>
1509
- ): Promise<void | unknown[]> {
1517
+ relationship: ManyRelationship | BelongsToRelationship,
1518
+ options: any
1519
+ ): RSVP.Promise<unknown> {
1510
1520
  if (HAS_RECORD_DATA_PACKAGE) {
1511
1521
  if (!resource) {
1512
- return resolve();
1522
+ return resolve([]);
1513
1523
  }
1514
1524
  const { definition, state } = relationship;
1515
1525
  let adapter = this.adapterFor(definition.type);
@@ -1554,7 +1564,7 @@ abstract class CoreStore extends Service {
1554
1564
 
1555
1565
  // we were explicitly told we have no data and no links.
1556
1566
  // TODO if the relationshipIsStale, should we hit the adapter anyway?
1557
- return resolve();
1567
+ return resolve([]);
1558
1568
  }
1559
1569
  assert(`hasMany only works with the @ember-data/record-data package`);
1560
1570
  }
@@ -1567,7 +1577,7 @@ abstract class CoreStore extends Service {
1567
1577
  @param {Relationship} relationship
1568
1578
  @return {Promise} promise
1569
1579
  */
1570
- findBelongsTo(internalModel, link, relationship, options): Promise<InternalModel> {
1580
+ findBelongsTo(internalModel, link, relationship, options) {
1571
1581
  if (DEBUG) {
1572
1582
  assertDestroyingStore(this, 'findBelongsTo');
1573
1583
  }
@@ -1585,25 +1595,19 @@ abstract class CoreStore extends Service {
1585
1595
  return _findBelongsTo(adapter, this, internalModel, link, relationship, options);
1586
1596
  }
1587
1597
 
1588
- _fetchBelongsToLinkFromResource(
1589
- resource,
1590
- parentInternalModel: InternalModel,
1591
- relationshipMeta,
1592
- options
1593
- ): Promise<InternalModel | null> {
1598
+ _fetchBelongsToLinkFromResource(resource, parentInternalModel, relationshipMeta, options) {
1594
1599
  if (!resource || !resource.links || !resource.links.related) {
1595
1600
  // should we warn here, not sure cause its an internal method
1596
1601
  return resolve(null);
1597
1602
  }
1598
- return this.findBelongsTo(parentInternalModel, resource.links.related, relationshipMeta, options);
1603
+ return this.findBelongsTo(parentInternalModel, resource.links.related, relationshipMeta, options).then(
1604
+ (internalModel) => {
1605
+ return internalModel ? internalModel.getRecord() : null;
1606
+ }
1607
+ );
1599
1608
  }
1600
1609
 
1601
- _findBelongsToByJsonApiResource(
1602
- resource,
1603
- parentInternalModel: InternalModel,
1604
- relationshipMeta,
1605
- options
1606
- ): Promise<InternalModel | null> {
1610
+ _findBelongsToByJsonApiResource(resource, parentInternalModel, relationshipMeta, options) {
1607
1611
  if (!resource) {
1608
1612
  return resolve(null);
1609
1613
  }
@@ -1622,7 +1626,7 @@ abstract class CoreStore extends Service {
1622
1626
  // short circuit if we are already loading
1623
1627
  let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
1624
1628
  if (pendingRequest) {
1625
- return pendingRequest.then(() => internalModel);
1629
+ return pendingRequest.then(() => internalModel.getRecord());
1626
1630
  }
1627
1631
  }
1628
1632
 
@@ -1655,12 +1659,14 @@ abstract class CoreStore extends Service {
1655
1659
  let resourceIsLocal = !localDataIsEmpty && resource.data.id === null;
1656
1660
 
1657
1661
  if (internalModel && resourceIsLocal) {
1658
- return resolve(internalModel);
1662
+ return resolve(internalModel.getRecord());
1659
1663
  }
1660
1664
 
1661
1665
  // fetch by data
1662
1666
  if (internalModel && !localDataIsEmpty) {
1663
- return this._scheduleFetch(internalModel, options);
1667
+ return this._scheduleFetch(internalModel, options).then(() => {
1668
+ return internalModel.getRecord();
1669
+ });
1664
1670
  }
1665
1671
 
1666
1672
  // we were explicitly told we have no data and no links.
@@ -1719,7 +1725,7 @@ abstract class CoreStore extends Service {
1719
1725
  @param {Object} options optional, may include `adapterOptions` hash which will be passed to adapter.query
1720
1726
  @return {Promise} promise
1721
1727
  */
1722
- query(modelName: string, query, options): PromiseArray<RecordInstance, AdapterPopulatedRecordArray> {
1728
+ query(modelName: string, query, options): PromiseArray<DSModel> {
1723
1729
  if (DEBUG) {
1724
1730
  assertDestroyingStore(this, 'query');
1725
1731
  }
@@ -1737,10 +1743,10 @@ abstract class CoreStore extends Service {
1737
1743
  }
1738
1744
 
1739
1745
  let normalizedModelName = normalizeModelName(modelName);
1740
- return promiseArray(this._query(normalizedModelName, query, null, adapterOptionsWrapper));
1746
+ return this._query(normalizedModelName, query, null, adapterOptionsWrapper);
1741
1747
  }
1742
1748
 
1743
- _query(modelName: string, query, array, options): Promise<AdapterPopulatedRecordArray> {
1749
+ _query(modelName: string, query, array, options): PromiseArray<DSModel> {
1744
1750
  assert(`You need to pass a model name to the store's query method`, isPresent(modelName));
1745
1751
  assert(`You need to pass a query hash to the store's query method`, query);
1746
1752
  assert(
@@ -1756,7 +1762,7 @@ abstract class CoreStore extends Service {
1756
1762
  typeof adapter.query === 'function'
1757
1763
  );
1758
1764
 
1759
- return _query(adapter, this, modelName, query, array, options) as unknown as Promise<AdapterPopulatedRecordArray>;
1765
+ return promiseArray(_query(adapter, this, modelName, query, array, options));
1760
1766
  }
1761
1767
 
1762
1768
  /**
@@ -1857,7 +1863,7 @@ abstract class CoreStore extends Service {
1857
1863
  @param {Object} options optional, may include `adapterOptions` hash which will be passed to adapter.queryRecord
1858
1864
  @return {Promise} promise which resolves with the found record or `null`
1859
1865
  */
1860
- queryRecord(modelName: string, query, options): PromiseObject<RecordInstance | null> {
1866
+ queryRecord(modelName, query, options) {
1861
1867
  if (DEBUG) {
1862
1868
  assertDestroyingStore(this, 'queryRecord');
1863
1869
  }
@@ -1882,17 +1888,15 @@ abstract class CoreStore extends Service {
1882
1888
  typeof adapter.queryRecord === 'function'
1883
1889
  );
1884
1890
 
1885
- const promise: Promise<InternalModel | null> = _queryRecord(
1886
- adapter,
1887
- this,
1888
- normalizedModelName,
1889
- query,
1890
- adapterOptionsWrapper
1891
- ) as Promise<InternalModel | null>;
1892
-
1893
1891
  return promiseObject(
1894
- promise.then((internalModel: InternalModel | null) => {
1895
- return internalModel ? internalModel.getRecord() : null;
1892
+ _queryRecord(adapter, this, normalizedModelName, query, adapterOptionsWrapper).then((internalModel) => {
1893
+ // the promise returned by store.queryRecord is expected to resolve with
1894
+ // an instance of Model
1895
+ if (internalModel) {
1896
+ return internalModel.getRecord();
1897
+ }
1898
+
1899
+ return null;
1896
1900
  })
1897
1901
  );
1898
1902
  }
@@ -2085,10 +2089,7 @@ abstract class CoreStore extends Service {
2085
2089
  @param {Object} options
2086
2090
  @return {Promise} promise
2087
2091
  */
2088
- findAll(
2089
- modelName: string,
2090
- options: { reload?: boolean; backgroundReload?: boolean } = {}
2091
- ): PromiseArray<RecordInstance, RecordArray> {
2092
+ findAll(modelName, options) {
2092
2093
  if (DEBUG) {
2093
2094
  assertDestroyingStore(this, 'findAll');
2094
2095
  }
@@ -2101,7 +2102,7 @@ abstract class CoreStore extends Service {
2101
2102
  let normalizedModelName = normalizeModelName(modelName);
2102
2103
  let fetch = this._fetchAll(normalizedModelName, this.peekAll(normalizedModelName), options);
2103
2104
 
2104
- return promiseArray(fetch);
2105
+ return fetch;
2105
2106
  }
2106
2107
 
2107
2108
  /**
@@ -2111,11 +2112,7 @@ abstract class CoreStore extends Service {
2111
2112
  @param {RecordArray} array
2112
2113
  @return {Promise} promise
2113
2114
  */
2114
- _fetchAll(
2115
- modelName: string,
2116
- array: RecordArray,
2117
- options: { reload?: boolean; backgroundReload?: boolean }
2118
- ): Promise<RecordArray> {
2115
+ _fetchAll(modelName, array, options: { reload?: boolean; backgroundReload?: boolean } = {}) {
2119
2116
  let adapter = this.adapterFor(modelName);
2120
2117
 
2121
2118
  assert(`You tried to load all records but you have no adapter (for ${modelName})`, adapter);
@@ -2126,7 +2123,7 @@ abstract class CoreStore extends Service {
2126
2123
 
2127
2124
  if (options.reload) {
2128
2125
  set(array, 'isUpdating', true);
2129
- return _findAll(adapter, this, modelName, options);
2126
+ return promiseArray(_findAll(adapter, this, modelName, options));
2130
2127
  }
2131
2128
 
2132
2129
  let snapshotArray = array._createSnapshot(options);
@@ -2137,12 +2134,12 @@ abstract class CoreStore extends Service {
2137
2134
  (!adapter.shouldReloadAll && snapshotArray.length === 0)
2138
2135
  ) {
2139
2136
  set(array, 'isUpdating', true);
2140
- return _findAll(adapter, this, modelName, options);
2137
+ return promiseArray(_findAll(adapter, this, modelName, options));
2141
2138
  }
2142
2139
  }
2143
2140
 
2144
2141
  if (options.backgroundReload === false) {
2145
- return resolve(array);
2142
+ return promiseArray(Promise.resolve(array));
2146
2143
  }
2147
2144
 
2148
2145
  if (
@@ -2154,7 +2151,7 @@ abstract class CoreStore extends Service {
2154
2151
  _findAll(adapter, this, modelName, options);
2155
2152
  }
2156
2153
 
2157
- return resolve(array);
2154
+ return promiseArray(Promise.resolve(array));
2158
2155
  }
2159
2156
 
2160
2157
  /**
@@ -2162,7 +2159,7 @@ abstract class CoreStore extends Service {
2162
2159
  @param {String} modelName
2163
2160
  @private
2164
2161
  */
2165
- _didUpdateAll(modelName: string): void {
2162
+ _didUpdateAll(modelName) {
2166
2163
  this.recordArrayManager._didUpdateAll(modelName);
2167
2164
  }
2168
2165
 
@@ -2261,11 +2258,7 @@ abstract class CoreStore extends Service {
2261
2258
  @param {Resolver} resolver
2262
2259
  @param {Object} options
2263
2260
  */
2264
- scheduleSave(
2265
- internalModel: InternalModel,
2266
- resolver: RSVP.Deferred<void>,
2267
- options: FindOptions
2268
- ): void | Promise<void> {
2261
+ scheduleSave(internalModel: InternalModel, resolver: RSVP.Deferred<void>, options): void | RSVP.Promise<void> {
2269
2262
  if (internalModel._isRecordFullyDeleted()) {
2270
2263
  resolver.resolve();
2271
2264
  return resolver.promise;
@@ -2286,8 +2279,9 @@ abstract class CoreStore extends Service {
2286
2279
  operation = 'deleteRecord';
2287
2280
  }
2288
2281
 
2289
- const saveOptions = Object.assign({ [SaveOp]: operation }, options);
2290
- let fetchManagerPromise = this._fetchManager.scheduleSave(internalModel.identifier, saveOptions);
2282
+ options[SaveOp] = operation;
2283
+
2284
+ let fetchManagerPromise = this._fetchManager.scheduleSave(internalModel.identifier, options);
2291
2285
  let promise = fetchManagerPromise.then(
2292
2286
  (payload) => {
2293
2287
  /*
@@ -2828,6 +2822,10 @@ abstract class CoreStore extends Service {
2828
2822
  serializer.pushPayload(this, payload);
2829
2823
  }
2830
2824
 
2825
+ reloadManyArray(manyArray, internalModel, key, options) {
2826
+ return internalModel.reloadHasMany(key, options);
2827
+ }
2828
+
2831
2829
  reloadBelongsTo(belongsToProxy, internalModel, key, options) {
2832
2830
  return internalModel.reloadBelongsTo(key, options);
2833
2831
  }
@@ -2854,13 +2852,13 @@ abstract class CoreStore extends Service {
2854
2852
  return internalModel!.createSnapshot(options).serialize(options);
2855
2853
  }
2856
2854
 
2857
- saveRecord(record: RecordInstance, options?: Dict<unknown>): Promise<RecordInstance> {
2855
+ saveRecord(record: RecordInstance, options?: Dict<unknown>): RSVP.Promise<RecordInstance> {
2858
2856
  let identifier = recordIdentifierFor(record);
2859
2857
  let internalModel = internalModelFactoryFor(this).peek(identifier);
2860
2858
  // TODO we used to check if the record was destroyed here
2861
2859
  // Casting can be removed once REQUEST_SERVICE ff is turned on
2862
2860
  // because a `Record` is provided there will always be a matching internalModel
2863
- return (internalModel!.save(options) as Promise<void>).then(() => record);
2861
+ return (internalModel!.save(options) as RSVP.Promise<void>).then(() => record);
2864
2862
  }
2865
2863
 
2866
2864
  relationshipReferenceFor(identifier: RecordIdentifier, key: string): BelongsToReference | HasManyReference {
@@ -2910,9 +2908,7 @@ abstract class CoreStore extends Service {
2910
2908
  // it can be reproduced in partner tests by running
2911
2909
  // node ./scripts/packages-for-commit.js && yarn test-external:ember-observer
2912
2910
  if (_RecordData === undefined) {
2913
- _RecordData = (
2914
- importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
2915
- ).RecordData as RecordDataConstruct;
2911
+ _RecordData = require('@ember-data/record-data/-private').RecordData as RecordDataConstruct;
2916
2912
  }
2917
2913
 
2918
2914
  let identifier = this.identifierCache.getOrCreateRecordIdentifier({
@@ -2970,7 +2966,7 @@ abstract class CoreStore extends Service {
2970
2966
  @param {Object} payload
2971
2967
  @return {Object} The normalized payload
2972
2968
  */
2973
- normalize(modelName: string, payload) {
2969
+ normalize(modelName, payload) {
2974
2970
  if (DEBUG) {
2975
2971
  assertDestroyingStore(this, 'normalize');
2976
2972
  }
@@ -2986,7 +2982,7 @@ abstract class CoreStore extends Service {
2986
2982
  let model = this.modelFor(normalizedModelName);
2987
2983
  assert(
2988
2984
  `You must define a normalize method in your serializer in order to call store.normalize`,
2989
- serializer?.normalize
2985
+ serializer.normalize
2990
2986
  );
2991
2987
  return serializer.normalize(model, payload);
2992
2988
  }
@@ -3100,7 +3096,7 @@ abstract class CoreStore extends Service {
3100
3096
  @param {String} modelName the record to serialize
3101
3097
  @return {Serializer}
3102
3098
  */
3103
- serializerFor(modelName: string): MinimumSerializerInterface | null {
3099
+ serializerFor(modelName) {
3104
3100
  if (DEBUG) {
3105
3101
  assertDestroyingStore(this, 'serializerFor');
3106
3102
  }
@@ -3136,29 +3132,30 @@ abstract class CoreStore extends Service {
3136
3132
  return serializer;
3137
3133
  }
3138
3134
 
3139
- return null;
3135
+ assert(
3136
+ `No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
3137
+ serializer !== undefined
3138
+ );
3140
3139
  }
3141
3140
 
3142
3141
  destroy() {
3143
3142
  // enqueue destruction of any adapters/serializers we have created
3144
3143
  for (let adapterName in this._adapterCache) {
3145
- let adapter = this._adapterCache[adapterName]!;
3144
+ let adapter = this._adapterCache[adapterName];
3146
3145
  if (typeof adapter.destroy === 'function') {
3147
3146
  adapter.destroy();
3148
3147
  }
3149
3148
  }
3150
3149
 
3151
3150
  for (let serializerName in this._serializerCache) {
3152
- let serializer = this._serializerCache[serializerName]!;
3151
+ let serializer = this._serializerCache[serializerName];
3153
3152
  if (typeof serializer.destroy === 'function') {
3154
3153
  serializer.destroy();
3155
3154
  }
3156
3155
  }
3157
3156
 
3158
3157
  if (HAS_RECORD_DATA_PACKAGE) {
3159
- const peekGraph = (
3160
- importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
3161
- ).peekGraph;
3158
+ const peekGraph = require('@ember-data/record-data/-private').peekGraph;
3162
3159
  let graph = peekGraph(this);
3163
3160
  if (graph) {
3164
3161
  graph.destroy();
@@ -3178,9 +3175,7 @@ abstract class CoreStore extends Service {
3178
3175
  // since then we avoid churning relationships
3179
3176
  // during unload
3180
3177
  if (HAS_RECORD_DATA_PACKAGE) {
3181
- const peekGraph = (
3182
- importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')
3183
- ).peekGraph;
3178
+ const peekGraph = require('@ember-data/record-data/-private').peekGraph;
3184
3179
  let graph = peekGraph(this);
3185
3180
  if (graph) {
3186
3181
  graph.willDestroy();
@@ -3214,6 +3209,24 @@ abstract class CoreStore extends Service {
3214
3209
  }
3215
3210
  }
3216
3211
  }
3212
+
3213
+ _updateInternalModel(internalModel: InternalModel) {
3214
+ if (this._updatedInternalModels.push(internalModel) !== 1) {
3215
+ return;
3216
+ }
3217
+
3218
+ emberBackburner.schedule('actions', this, this._flushUpdatedInternalModels);
3219
+ }
3220
+
3221
+ _flushUpdatedInternalModels() {
3222
+ let updated = this._updatedInternalModels;
3223
+
3224
+ for (let i = 0, l = updated.length; i < l; i++) {
3225
+ updated[i]._triggerDeferredTriggers();
3226
+ }
3227
+
3228
+ updated.length = 0;
3229
+ }
3217
3230
  }
3218
3231
 
3219
3232
  export default CoreStore;