@ember-data/store 4.2.0-alpha.1 → 4.2.0-alpha.10

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 (29) hide show
  1. package/addon/-private/identifiers/cache.ts +3 -16
  2. package/addon/-private/identifiers/is-stable-identifier.ts +2 -2
  3. package/addon/-private/index.ts +1 -3
  4. package/addon/-private/system/core-store.ts +182 -883
  5. package/addon/-private/system/ds-model-store.ts +20 -111
  6. package/addon/-private/system/fetch-manager.ts +2 -1
  7. package/addon/-private/system/model/internal-model.ts +92 -345
  8. package/addon/-private/system/model/shim-model-class.ts +15 -16
  9. package/addon/-private/system/model/states.js +2 -14
  10. package/addon/-private/system/record-array-manager.js +21 -70
  11. package/addon/-private/system/record-arrays/adapter-populated-record-array.js +1 -20
  12. package/addon/-private/system/record-arrays/record-array.js +1 -8
  13. package/addon/-private/system/record-data-for.ts +10 -8
  14. package/addon/-private/system/record-notification-manager.ts +11 -10
  15. package/addon/-private/system/references/belongs-to.ts +32 -67
  16. package/addon/-private/system/references/has-many.ts +21 -41
  17. package/addon/-private/system/references/record.ts +15 -27
  18. package/addon/-private/system/references/reference.ts +4 -11
  19. package/addon/-private/system/schema-definition-service.ts +2 -2
  20. package/addon/-private/system/snapshot.ts +28 -48
  21. package/addon/-private/system/store/finders.js +2 -96
  22. package/addon/-private/system/store/internal-model-factory.ts +34 -28
  23. package/addon/-private/system/store/record-data-store-wrapper.ts +28 -36
  24. package/addon/-private/system/weak-cache.ts +125 -0
  25. package/addon/-private/ts-interfaces/identifier.ts +2 -2
  26. package/addon/-private/ts-interfaces/minimum-adapter-interface.ts +0 -1
  27. package/addon/-private/ts-interfaces/schema-definition-service.ts +2 -2
  28. package/package.json +15 -15
  29. package/addon/-private/system/deprecated-evented.js +0 -92
@@ -3,8 +3,8 @@
3
3
  */
4
4
  import { getOwner } from '@ember/application';
5
5
  import { A } from '@ember/array';
6
- import { assert, deprecate, inspect, warn } from '@ember/debug';
7
- import { computed, defineProperty, get, set } from '@ember/object';
6
+ import { assert, inspect, warn } from '@ember/debug';
7
+ import { set } from '@ember/object';
8
8
  import { _backburner as emberBackburner } from '@ember/runloop';
9
9
  import type { Backburner } from '@ember/runloop/-private/backburner';
10
10
  import Service from '@ember/service';
@@ -14,24 +14,9 @@ import { DEBUG } from '@glimmer/env';
14
14
  import Ember from 'ember';
15
15
 
16
16
  import require from 'require';
17
- import { all, default as RSVP, defer, Promise, resolve } from 'rsvp';
17
+ import { all, default as RSVP, Promise, resolve } from 'rsvp';
18
18
 
19
- import {
20
- CUSTOM_MODEL_CLASS,
21
- RECORD_DATA_ERRORS,
22
- RECORD_DATA_STATE,
23
- REQUEST_SERVICE,
24
- } from '@ember-data/canary-features';
25
- import {
26
- HAS_ADAPTER_PACKAGE,
27
- HAS_EMBER_DATA_PACKAGE,
28
- HAS_RECORD_DATA_PACKAGE,
29
- HAS_SERIALIZER_PACKAGE,
30
- } from '@ember-data/private-build-infra';
31
- import {
32
- DEPRECATE_DEFAULT_ADAPTER,
33
- DEPRECATE_LEGACY_TEST_REGISTRATIONS,
34
- } from '@ember-data/private-build-infra/deprecations';
19
+ import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
35
20
  import type {
36
21
  BelongsToRelationship,
37
22
  ManyRelationship,
@@ -39,8 +24,7 @@ import type {
39
24
  } from '@ember-data/record-data/-private';
40
25
  import type { RelationshipState } from '@ember-data/record-data/-private/graph/-state';
41
26
 
42
- import type { IdentifierCache } from '../identifiers/cache';
43
- import { identifierCacheFor } from '../identifiers/cache';
27
+ import { IdentifierCache } from '../identifiers/cache';
44
28
  import type { DSModel } from '../ts-interfaces/ds-model';
45
29
  import type {
46
30
  CollectionResourceDocument,
@@ -68,7 +52,6 @@ import constructResource from '../utils/construct-resource';
68
52
  import promiseRecord from '../utils/promise-record';
69
53
  import edBackburner from './backburner';
70
54
  import coerceId, { ensureStringId } from './coerce-id';
71
- import { errorsArrayToHash } from './errors-utils';
72
55
  import FetchManager, { SaveOp } from './fetch-manager';
73
56
  import type InternalModel from './model/internal-model';
74
57
  import {
@@ -86,9 +69,7 @@ import NotificationManager from './record-notification-manager';
86
69
  import type { BelongsToReference, HasManyReference } from './references';
87
70
  import { RecordReference } from './references';
88
71
  import type RequestCache from './request-cache';
89
- import type { default as Snapshot, PrivateSnapshot } from './snapshot';
90
- import { _bind, _guard, _objectIsAlive, guardDestroyedStore } from './store/common';
91
- import { _find, _findAll, _findBelongsTo, _findHasMany, _findMany, _query, _queryRecord } from './store/finders';
72
+ import { _findAll, _findBelongsTo, _findHasMany, _query, _queryRecord } from './store/finders';
92
73
  import {
93
74
  internalModelFactoryFor,
94
75
  peekRecordIdentifier,
@@ -96,7 +77,7 @@ import {
96
77
  setRecordIdentifier,
97
78
  } from './store/internal-model-factory';
98
79
  import RecordDataStoreWrapper from './store/record-data-store-wrapper';
99
- import { normalizeResponseHelper } from './store/serializer-response';
80
+ import WeakCache from './weak-cache';
100
81
 
101
82
  type RecordDataConstruct = typeof RecordDataClass;
102
83
  let _RecordData: RecordDataConstruct | undefined;
@@ -104,18 +85,8 @@ let _RecordData: RecordDataConstruct | undefined;
104
85
  const { ENV } = Ember;
105
86
  type AsyncTrackingToken = Readonly<{ label: string; trace: Error | string }>;
106
87
  type PromiseArray<T> = Promise<T[]>;
107
- type PendingFetchItem = {
108
- internalModel: InternalModel;
109
- resolver: RSVP.Deferred<InternalModel>;
110
- options: any;
111
- trace?: Error;
112
- };
113
- type PendingSaveItem = {
114
- snapshot: Snapshot;
115
- resolver: RSVP.Deferred<void>;
116
- };
117
-
118
- const RECORD_REFERENCES = new WeakMap<StableRecordIdentifier, RecordReference>();
88
+
89
+ const RECORD_REFERENCES = new WeakCache<StableRecordIdentifier, RecordReference>(DEBUG ? 'reference' : '');
119
90
 
120
91
  function freeze<T>(obj: T): T {
121
92
  if (typeof Object.freeze === 'function') {
@@ -125,26 +96,6 @@ function freeze<T>(obj: T): T {
125
96
  return obj;
126
97
  }
127
98
 
128
- function deprecateTestRegistration(factoryType: 'adapter', factoryName: '-json-api'): void;
129
- function deprecateTestRegistration(factoryType: 'serializer', factoryName: '-json-api' | '-rest' | '-default'): void;
130
- function deprecateTestRegistration(
131
- factoryType: 'serializer' | 'adapter',
132
- factoryName: '-json-api' | '-rest' | '-default'
133
- ): void {
134
- deprecate(
135
- `You looked up the ${factoryType} "${factoryName}" but it was not found. Likely this means you are using a legacy ember-qunit moduleFor helper. Add "needs: ['${factoryType}:${factoryName}']", "integration: true", or refactor to modern syntax to resolve this deprecation.`,
136
- false,
137
- {
138
- id: 'ember-data:-legacy-test-registrations',
139
- until: '3.17',
140
- for: '@ember-data/store',
141
- since: {
142
- available: '3.15',
143
- enabled: '3.15',
144
- },
145
- }
146
- );
147
- }
148
99
  /**
149
100
  The store contains all of the data for records loaded from the server.
150
101
  It is also responsible for creating instances of `Model` that wrap
@@ -218,9 +169,6 @@ function deprecateTestRegistration(
218
169
  @public
219
170
  @extends Ember.Service
220
171
  */
221
- interface CoreStore {
222
- adapter: string;
223
- }
224
172
 
225
173
  abstract class CoreStore extends Service {
226
174
  /**
@@ -232,6 +180,7 @@ abstract class CoreStore extends Service {
232
180
  public recordArrayManager: RecordArrayManager = new RecordArrayManager({ store: this });
233
181
 
234
182
  declare _notificationManager: NotificationManager;
183
+ declare identifierCache: IdentifierCache;
235
184
  private _adapterCache = Object.create(null);
236
185
  private _serializerCache = Object.create(null);
237
186
  public _storeWrapper = new RecordDataStoreWrapper(this);
@@ -243,20 +192,14 @@ abstract class CoreStore extends Service {
243
192
  These queues are currently controlled by a flush scheduled into
244
193
  ember-data's custom backburner instance.
245
194
  */
246
- // used for coalescing record save requests
247
- private _pendingSave: PendingSaveItem[] = [];
248
195
  // used for coalescing internal model updates
249
196
  private _updatedInternalModels: InternalModel[] = [];
250
197
 
251
- // used to keep track of all the find requests that need to be coalesced
252
- private _pendingFetch = new Map<string, PendingFetchItem[]>();
253
-
254
198
  declare _fetchManager: FetchManager;
255
199
  declare _schemaDefinitionService: SchemaDefinitionService;
256
200
 
257
201
  // DEBUG-only properties
258
202
  declare _trackedAsyncRequests: AsyncTrackingToken[];
259
- shouldAssertMethodCallsOnDestroyedStore: boolean = true;
260
203
  shouldTrackAsyncRequests: boolean = false;
261
204
  generateStackTracesForTrackedRequests: boolean = false;
262
205
  declare _trackAsyncRequestStart: (str: string) => void;
@@ -310,64 +253,27 @@ abstract class CoreStore extends Service {
310
253
  constructor() {
311
254
  super(...arguments);
312
255
 
313
- if (REQUEST_SERVICE) {
314
- this._fetchManager = new FetchManager(this);
315
- }
316
- if (CUSTOM_MODEL_CLASS) {
317
- this._notificationManager = new NotificationManager(this);
318
- this.__recordDataFor = this.__recordDataFor.bind(this);
319
- }
256
+ RECORD_REFERENCES._generator = (identifier) => {
257
+ return new RecordReference(this, identifier);
258
+ };
259
+
260
+ this._fetchManager = new FetchManager(this);
261
+ this._notificationManager = new NotificationManager(this);
262
+ this.__recordDataFor = this.__recordDataFor.bind(this);
263
+
264
+ /**
265
+ * Provides access to the IdentifierCache instance
266
+ * for this store.
267
+ *
268
+ * The IdentifierCache can be used to generate or
269
+ * retrieve a stable unique identifier for any resource.
270
+ *
271
+ * @property {IdentifierCache} identifierCache
272
+ * @public
273
+ */
274
+ this.identifierCache = new IdentifierCache();
320
275
 
321
276
  if (DEBUG) {
322
- if (HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE) {
323
- // support for legacy moduleFor style unit tests
324
- // that did not include transforms in "needs"
325
- // or which were not set to integration:true
326
- // that were relying on ember-test-helpers
327
- // doing an auto-registration of the transform
328
- // or us doing one
329
- const Mapping = {
330
- date: 'DateTransform',
331
- boolean: 'BooleanTransform',
332
- number: 'NumberTransform',
333
- string: 'StringTransform',
334
- };
335
- type MapKeys = keyof typeof Mapping;
336
- const keys = Object.keys(Mapping) as MapKeys[];
337
- let shouldWarn = false;
338
-
339
- let owner = getOwner(this);
340
- keys.forEach((attributeType) => {
341
- const transformFactory = owner.factoryFor(`transform:${attributeType}`);
342
-
343
- if (!transformFactory) {
344
- // we don't deprecate this because the moduleFor style tests with the closed
345
- // resolver will be deprecated on their own. When that deprecation completes
346
- // we can drop this.
347
- const Transform = require(`@ember-data/serializer/-private`)[Mapping[attributeType]];
348
- owner.register(`transform:${attributeType}`, Transform);
349
- shouldWarn = true;
350
- }
351
- });
352
-
353
- if (shouldWarn) {
354
- deprecate(
355
- `You are relying on the automatic registration of the transforms "date", "number", "boolean", and "string". Likely this means you are using a legacy ember-qunit moduleFor helper. Add "needs: ['transform:date', 'transform:boolean', 'transform:number', 'transform:string']", "integration: true", or refactor to modern syntax to resolve this deprecation.`,
356
- false,
357
- {
358
- id: 'ember-data:-legacy-test-registrations',
359
- until: '3.17',
360
- for: '@ember-data/store',
361
- since: {
362
- available: '3.15',
363
- enabled: '3.15',
364
- },
365
- }
366
- );
367
- }
368
- }
369
-
370
- this.shouldAssertMethodCallsOnDestroyedStore = this.shouldAssertMethodCallsOnDestroyedStore || false;
371
277
  if (this.shouldTrackAsyncRequests === undefined) {
372
278
  this.shouldTrackAsyncRequests = false;
373
279
  }
@@ -377,14 +283,14 @@ abstract class CoreStore extends Service {
377
283
 
378
284
  this._trackedAsyncRequests = [];
379
285
  this._trackAsyncRequestStart = (label) => {
380
- let trace =
286
+ let trace: string | Error =
381
287
  'set `store.generateStackTracesForTrackedRequests = true;` to get a detailed trace for where this request originated';
382
288
 
383
289
  if (this.generateStackTracesForTrackedRequests) {
384
290
  try {
385
291
  throw new Error(`EmberData TrackedRequest: ${label}`);
386
292
  } catch (e) {
387
- trace = e;
293
+ trace = e as Error;
388
294
  }
389
295
  }
390
296
 
@@ -421,24 +327,7 @@ abstract class CoreStore extends Service {
421
327
  }
422
328
 
423
329
  getRequestStateService(): RequestCache {
424
- if (REQUEST_SERVICE) {
425
- return this._fetchManager.requestCache;
426
- }
427
- assert('RequestService is not available unless the feature flag is on and running on a canary build', false);
428
- }
429
-
430
- /**
431
- * Provides access to the IdentifierCache instance
432
- * for this store.
433
- *
434
- * The IdentifierCache can be used to generate or
435
- * retrieve a stable unique identifier for any resource.
436
- *
437
- * @property {IdentifierCache} identifierCache
438
- * @public
439
- */
440
- get identifierCache(): IdentifierCache {
441
- return identifierCacheFor(this);
330
+ return this._fetchManager.requestCache;
442
331
  }
443
332
 
444
333
  _instantiateRecord(
@@ -448,55 +337,51 @@ abstract class CoreStore extends Service {
448
337
  identifier: StableRecordIdentifier,
449
338
  properties?: { [key: string]: any }
450
339
  ) {
451
- if (CUSTOM_MODEL_CLASS) {
452
- // assert here
453
- if (properties !== undefined) {
454
- assert(
455
- `You passed '${properties}' as properties for record creation instead of an object.`,
456
- typeof properties === 'object' && properties !== null
457
- );
458
-
459
- if ('id' in properties) {
460
- internalModel.setId(properties.id);
461
- }
340
+ // assert here
341
+ if (properties !== undefined) {
342
+ assert(
343
+ `You passed '${properties}' as properties for record creation instead of an object.`,
344
+ typeof properties === 'object' && properties !== null
345
+ );
462
346
 
463
- // convert relationship Records to RecordDatas before passing to RecordData
464
- let defs = this._relationshipsDefinitionFor(modelName);
465
-
466
- if (defs !== null) {
467
- let keys = Object.keys(properties);
468
- let relationshipValue;
469
-
470
- for (let i = 0; i < keys.length; i++) {
471
- let prop = keys[i];
472
- let def = defs[prop];
473
-
474
- if (def !== undefined) {
475
- if (def.kind === 'hasMany') {
476
- if (DEBUG) {
477
- assertRecordsPassedToHasMany(properties[prop]);
478
- }
479
- relationshipValue = extractRecordDatasFromRecords(properties[prop]);
480
- } else {
481
- relationshipValue = extractRecordDataFromRecord(properties[prop]);
482
- }
347
+ if ('id' in properties) {
348
+ internalModel.setId(properties.id);
349
+ }
350
+
351
+ // convert relationship Records to RecordDatas before passing to RecordData
352
+ let defs = this._relationshipsDefinitionFor({ type: modelName });
353
+
354
+ if (defs !== null) {
355
+ let keys = Object.keys(properties);
356
+ let relationshipValue;
357
+
358
+ for (let i = 0; i < keys.length; i++) {
359
+ let prop = keys[i];
360
+ let def = defs[prop];
483
361
 
484
- properties[prop] = relationshipValue;
362
+ if (def !== undefined) {
363
+ if (def.kind === 'hasMany') {
364
+ if (DEBUG) {
365
+ assertRecordsPassedToHasMany(properties[prop]);
366
+ }
367
+ relationshipValue = extractRecordDatasFromRecords(properties[prop]);
368
+ } else {
369
+ relationshipValue = extractRecordDataFromRecord(properties[prop]);
485
370
  }
371
+
372
+ properties[prop] = relationshipValue;
486
373
  }
487
374
  }
488
375
  }
489
-
490
- // TODO guard against initRecordOptions no being there
491
- let createOptions = recordData._initRecordCreateOptions(properties);
492
- //TODO Igor pass a wrapper instead of RD
493
- let record = this.instantiateRecord(identifier, createOptions, this.__recordDataFor, this._notificationManager);
494
- setRecordIdentifier(record, identifier);
495
- //recordToInternalModelMap.set(record, internalModel);
496
- return record;
497
376
  }
498
377
 
499
- assert('should not be here, custom model class ff error', false);
378
+ // TODO guard against initRecordOptions no being there
379
+ let createOptions = recordData._initRecordCreateOptions(properties);
380
+ //TODO Igor pass a wrapper instead of RD
381
+ let record = this.instantiateRecord(identifier, createOptions, this.__recordDataFor, this._notificationManager);
382
+ setRecordIdentifier(record, identifier);
383
+ //recordToInternalModelMap.set(record, internalModel);
384
+ return record;
500
385
  }
501
386
 
502
387
  abstract instantiateRecord(
@@ -513,20 +398,12 @@ abstract class CoreStore extends Service {
513
398
  }
514
399
 
515
400
  // FeatureFlagged in the DSModelStore claas
516
- _attributesDefinitionFor(modelName: string, identifier?: StableRecordIdentifier): AttributesSchema {
517
- if (identifier) {
518
- return this.getSchemaDefinitionService().attributesDefinitionFor(identifier);
519
- } else {
520
- return this.getSchemaDefinitionService().attributesDefinitionFor(modelName);
521
- }
401
+ _attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
402
+ return this.getSchemaDefinitionService().attributesDefinitionFor(identifier);
522
403
  }
523
404
 
524
- _relationshipsDefinitionFor(modelName: string, identifier?: StableRecordIdentifier) {
525
- if (identifier) {
526
- return this.getSchemaDefinitionService().relationshipsDefinitionFor(identifier);
527
- } else {
528
- return this.getSchemaDefinitionService().relationshipsDefinitionFor(modelName);
529
- }
405
+ _relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }) {
406
+ return this.getSchemaDefinitionService().relationshipsDefinitionFor(identifier);
530
407
  }
531
408
 
532
409
  registerSchemaDefinitionService(schema: SchemaDefinitionService) {
@@ -534,15 +411,12 @@ abstract class CoreStore extends Service {
534
411
  }
535
412
 
536
413
  getSchemaDefinitionService(): SchemaDefinitionService {
537
- if (CUSTOM_MODEL_CLASS) {
538
- return this._schemaDefinitionService;
539
- }
540
- assert('need to enable CUSTOM_MODEL_CLASS feature flag in order to access SchemaDefinitionService');
414
+ return this._schemaDefinitionService;
541
415
  }
542
416
 
543
417
  // TODO Double check this return value is correct
544
418
  _relationshipMetaFor(modelName: string, id: string | null, key: string) {
545
- return this._relationshipsDefinitionFor(modelName)[key];
419
+ return this._relationshipsDefinitionFor({ type: modelName })[key];
546
420
  }
547
421
 
548
422
  /**
@@ -715,16 +589,12 @@ abstract class CoreStore extends Service {
715
589
  assertDestroyingStore(this, 'deleteRecord');
716
590
  }
717
591
  this._backburner.join(() => {
718
- if (CUSTOM_MODEL_CLASS) {
719
- let identifier = peekRecordIdentifier(record);
720
- if (identifier) {
721
- let internalModel = internalModelFactoryFor(this).peek(identifier);
722
- if (internalModel) {
723
- internalModel.deleteRecord();
724
- }
592
+ let identifier = peekRecordIdentifier(record);
593
+ if (identifier) {
594
+ let internalModel = internalModelFactoryFor(this).peek(identifier);
595
+ if (internalModel) {
596
+ internalModel.deleteRecord();
725
597
  }
726
- } else {
727
- record.deleteRecord();
728
598
  }
729
599
  });
730
600
  }
@@ -749,16 +619,12 @@ abstract class CoreStore extends Service {
749
619
  if (DEBUG) {
750
620
  assertDestroyingStore(this, 'unloadRecord');
751
621
  }
752
- if (CUSTOM_MODEL_CLASS) {
753
- let identifier = peekRecordIdentifier(record);
754
- if (identifier) {
755
- let internalModel = internalModelFactoryFor(this).peek(identifier);
756
- if (internalModel) {
757
- internalModel.unloadRecord();
758
- }
622
+ let identifier = peekRecordIdentifier(record);
623
+ if (identifier) {
624
+ let internalModel = internalModelFactoryFor(this).peek(identifier);
625
+ if (internalModel) {
626
+ internalModel.unloadRecord();
759
627
  }
760
- } else {
761
- record.unloadRecord();
762
628
  }
763
629
  }
764
630
 
@@ -1267,19 +1133,12 @@ abstract class CoreStore extends Service {
1267
1133
  return this._scheduleFetch(internalModel, options);
1268
1134
  }
1269
1135
 
1270
- //TODO double check about reloading
1271
- if (!REQUEST_SERVICE) {
1272
- if (internalModel.currentState.isLoading) {
1273
- return internalModel._promiseProxy;
1274
- }
1275
- } else {
1276
- if (internalModel.currentState.isLoading) {
1277
- let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
1278
- if (pendingRequest) {
1279
- return pendingRequest.then(() => Promise.resolve(internalModel));
1280
- }
1281
- return this._scheduleFetch(internalModel, options);
1136
+ if (internalModel.currentState.isLoading) {
1137
+ let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
1138
+ if (pendingRequest) {
1139
+ return pendingRequest.then(() => Promise.resolve(internalModel));
1282
1140
  }
1141
+ return this._scheduleFetch(internalModel, options);
1283
1142
  }
1284
1143
 
1285
1144
  return Promise.resolve(internalModel);
@@ -1316,29 +1175,6 @@ abstract class CoreStore extends Service {
1316
1175
  return promiseArray(all(promises).then(A, null, `DS: Store#findByIds of ${normalizedModelName} complete`));
1317
1176
  }
1318
1177
 
1319
- /**
1320
- This method is called by `findRecord` if it discovers that a particular
1321
- type/id pair hasn't been loaded yet to kick off a request to the
1322
- adapter.
1323
-
1324
- @method _fetchRecord
1325
- @private
1326
- @param {InternalModel} internalModel model
1327
- @return {Promise} promise
1328
- */
1329
- _fetchRecord(internalModel: InternalModel, options): Promise<InternalModel> {
1330
- let modelName = internalModel.modelName;
1331
- let adapter = this.adapterFor(modelName);
1332
-
1333
- assert(`You tried to find a record but you have no adapter (for ${modelName})`, adapter);
1334
- assert(
1335
- `You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`,
1336
- typeof adapter.findRecord === 'function'
1337
- );
1338
-
1339
- return _find(adapter, this, internalModel.modelClass, internalModel.id, internalModel, options);
1340
- }
1341
-
1342
1178
  _scheduleFetchMany(internalModels, options) {
1343
1179
  let fetches = new Array(internalModels.length);
1344
1180
 
@@ -1349,7 +1185,7 @@ abstract class CoreStore extends Service {
1349
1185
  return Promise.all(fetches);
1350
1186
  }
1351
1187
 
1352
- _scheduleFetchThroughFetchManager(internalModel: InternalModel, options = {}): RSVP.Promise<InternalModel> {
1188
+ _scheduleFetch(internalModel: InternalModel, options = {}): RSVP.Promise<InternalModel> {
1353
1189
  let generateStackTrace = this.generateStackTracesForTrackedRequests;
1354
1190
  // TODO remove this once we don't rely on state machine
1355
1191
  internalModel.send('loadingData');
@@ -1384,227 +1220,6 @@ abstract class CoreStore extends Service {
1384
1220
  );
1385
1221
  }
1386
1222
 
1387
- _scheduleFetch(internalModel: InternalModel, options): RSVP.Promise<InternalModel> {
1388
- if (REQUEST_SERVICE) {
1389
- return this._scheduleFetchThroughFetchManager(internalModel, options);
1390
- } else {
1391
- if (internalModel._promiseProxy) {
1392
- return internalModel._promiseProxy;
1393
- }
1394
-
1395
- assertIdentifierHasId(internalModel.identifier);
1396
-
1397
- let { id, modelName } = internalModel;
1398
- let resolver = defer<InternalModel>(`Fetching ${modelName}' with id: ${id}`);
1399
- let pendingFetchItem: PendingFetchItem = {
1400
- internalModel,
1401
- resolver,
1402
- options,
1403
- };
1404
-
1405
- if (DEBUG) {
1406
- if (this.generateStackTracesForTrackedRequests === true) {
1407
- let trace;
1408
-
1409
- try {
1410
- throw new Error(`Trace Origin for scheduled fetch for ${modelName}:${id}.`);
1411
- } catch (e) {
1412
- trace = e;
1413
- }
1414
-
1415
- // enable folks to discover the origin of this findRecord call when
1416
- // debugging. Ideally we would have a tracked queue for requests with
1417
- // labels or local IDs that could be used to merge this trace with
1418
- // the trace made available when we detect an async leak
1419
- pendingFetchItem.trace = trace;
1420
- }
1421
- }
1422
-
1423
- let promise = resolver.promise;
1424
-
1425
- internalModel.send('loadingData', promise);
1426
- if (this._pendingFetch.size === 0) {
1427
- emberBackburner.schedule('actions', this, this.flushAllPendingFetches);
1428
- }
1429
-
1430
- let fetches = this._pendingFetch;
1431
- let pending = fetches.get(modelName);
1432
-
1433
- if (pending === undefined) {
1434
- pending = [];
1435
- fetches.set(modelName, pending);
1436
- }
1437
-
1438
- pending.push(pendingFetchItem);
1439
-
1440
- return promise;
1441
- }
1442
- }
1443
-
1444
- flushAllPendingFetches() {
1445
- if (REQUEST_SERVICE) {
1446
- return;
1447
- //assert here
1448
- } else {
1449
- if (this.isDestroyed || this.isDestroying) {
1450
- return;
1451
- }
1452
-
1453
- this._pendingFetch.forEach(this._flushPendingFetchForType, this);
1454
- this._pendingFetch.clear();
1455
- }
1456
- }
1457
-
1458
- _flushPendingFetchForType(pendingFetchItems: PendingFetchItem[], modelName: string) {
1459
- let store = this;
1460
- let adapter = store.adapterFor(modelName);
1461
- let shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests;
1462
- let totalItems = pendingFetchItems.length;
1463
- let internalModels = new Array(totalItems);
1464
- let seeking = Object.create(null);
1465
-
1466
- let optionsMap = new WeakMap();
1467
-
1468
- for (let i = 0; i < totalItems; i++) {
1469
- let pendingItem = pendingFetchItems[i];
1470
- let internalModel = pendingItem.internalModel;
1471
- internalModels[i] = internalModel;
1472
- optionsMap.set(internalModel, pendingItem.options);
1473
- // We can remove this "not null" cast once we have enough typing
1474
- // to know we are only dealing with ExistingResourceIdentifierObjects
1475
- seeking[internalModel.id!] = pendingItem;
1476
- }
1477
-
1478
- function _fetchRecord(recordResolverPair) {
1479
- let recordFetch = store._fetchRecord(recordResolverPair.internalModel, recordResolverPair.options);
1480
-
1481
- recordResolverPair.resolver.resolve(recordFetch);
1482
- }
1483
-
1484
- function handleFoundRecords(foundInternalModels: InternalModel[], expectedInternalModels: InternalModel[]) {
1485
- // resolve found records
1486
- let found = Object.create(null);
1487
- for (let i = 0, l = foundInternalModels.length; i < l; i++) {
1488
- let internalModel = foundInternalModels[i];
1489
-
1490
- // We can remove this "not null" cast once we have enough typing
1491
- // to know we are only dealing with ExistingResourceIdentifierObjects
1492
- let pair = seeking[internalModel.id!];
1493
- found[internalModel.id!] = internalModel;
1494
-
1495
- if (pair) {
1496
- let resolver = pair.resolver;
1497
- resolver.resolve(internalModel);
1498
- }
1499
- }
1500
-
1501
- // reject missing records
1502
- let missingInternalModels: InternalModel[] = [];
1503
-
1504
- for (let i = 0, l = expectedInternalModels.length; i < l; i++) {
1505
- let internalModel = expectedInternalModels[i];
1506
-
1507
- // We can remove this "not null" cast once we have enough typing
1508
- // to know we are only dealing with ExistingResourceIdentifierObjects
1509
- if (!found[internalModel.id!]) {
1510
- missingInternalModels.push(internalModel);
1511
- }
1512
- }
1513
-
1514
- if (missingInternalModels.length) {
1515
- warn(
1516
- 'Ember Data expected to find records with the following ids in the adapter response but they were missing: [ "' +
1517
- missingInternalModels.map((r) => r.id).join('", "') +
1518
- '" ]',
1519
- false,
1520
- {
1521
- id: 'ds.store.missing-records-from-adapter',
1522
- }
1523
- );
1524
- rejectInternalModels(missingInternalModels);
1525
- }
1526
- }
1527
-
1528
- function rejectInternalModels(internalModels: InternalModel[], error?: Error) {
1529
- for (let i = 0, l = internalModels.length; i < l; i++) {
1530
- let internalModel = internalModels[i];
1531
-
1532
- // We can remove this "not null" cast once we have enough typing
1533
- // to know we are only dealing with ExistingResourceIdentifierObjects
1534
- let pair = seeking[internalModel.id!];
1535
-
1536
- if (pair) {
1537
- pair.resolver.reject(
1538
- error ||
1539
- new Error(
1540
- `Expected: '${internalModel}' to be present in the adapter provided payload, but it was not found.`
1541
- )
1542
- );
1543
- }
1544
- }
1545
- }
1546
-
1547
- if (shouldCoalesce) {
1548
- // TODO: Improve records => snapshots => records => snapshots
1549
- //
1550
- // We want to provide records to all store methods and snapshots to all
1551
- // adapter methods. To make sure we're doing that we're providing an array
1552
- // of snapshots to adapter.groupRecordsForFindMany(), which in turn will
1553
- // return grouped snapshots instead of grouped records.
1554
- //
1555
- // But since the _findMany() finder is a store method we need to get the
1556
- // records from the grouped snapshots even though the _findMany() finder
1557
- // will once again convert the records to snapshots for adapter.findMany()
1558
- let snapshots = new Array(totalItems);
1559
- for (let i = 0; i < totalItems; i++) {
1560
- let internalModel = internalModels[i];
1561
- snapshots[i] = internalModel.createSnapshot(optionsMap.get(internalModel));
1562
- }
1563
-
1564
- let groups;
1565
- if (adapter.groupRecordsForFindMany) {
1566
- groups = adapter.groupRecordsForFindMany(this, snapshots);
1567
- } else {
1568
- groups = [snapshots];
1569
- }
1570
-
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);
1576
-
1577
- for (let j = 0; j < totalInGroup; j++) {
1578
- let internalModel = group[j]._internalModel;
1579
-
1580
- groupedInternalModels[j] = internalModel;
1581
- ids[j] = internalModel.id;
1582
- }
1583
-
1584
- if (totalInGroup > 1) {
1585
- (function (groupedInternalModels) {
1586
- _findMany(adapter, store, modelName, ids, groupedInternalModels, optionsMap)
1587
- .then(function (foundInternalModels) {
1588
- handleFoundRecords(foundInternalModels, groupedInternalModels);
1589
- })
1590
- .catch(function (error) {
1591
- rejectInternalModels(groupedInternalModels, error);
1592
- });
1593
- })(groupedInternalModels);
1594
- } else if (ids.length === 1) {
1595
- let pair = seeking[groupedInternalModels[0].id];
1596
- _fetchRecord(pair);
1597
- } else {
1598
- assert("You cannot return an empty array from adapter's method groupRecordsForFindMany");
1599
- }
1600
- }
1601
- } else {
1602
- for (let i = 0; i < totalItems; i++) {
1603
- _fetchRecord(pendingFetchItems[i]);
1604
- }
1605
- }
1606
- }
1607
-
1608
1223
  /**
1609
1224
  Get the reference for the specified record.
1610
1225
 
@@ -1662,15 +1277,9 @@ abstract class CoreStore extends Service {
1662
1277
  isMaybeIdentifier(resourceIdentifier)
1663
1278
  );
1664
1279
 
1665
- let identifier: StableRecordIdentifier = identifierCacheFor(this).getOrCreateRecordIdentifier(resourceIdentifier);
1280
+ let identifier: StableRecordIdentifier = this.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
1666
1281
  if (identifier) {
1667
- if (RECORD_REFERENCES.has(identifier)) {
1668
- return RECORD_REFERENCES.get(identifier);
1669
- }
1670
-
1671
- let reference = new RecordReference(this, identifier);
1672
- RECORD_REFERENCES.set(identifier, reference);
1673
- return reference;
1282
+ return RECORD_REFERENCES.lookup(identifier);
1674
1283
  }
1675
1284
  }
1676
1285
 
@@ -1726,7 +1335,7 @@ abstract class CoreStore extends Service {
1726
1335
  peekRecord(identifier: ResourceIdentifierObject): RecordInstance | null;
1727
1336
  peekRecord(identifier: ResourceIdentifierObject | string, id?: string | number): RecordInstance | null {
1728
1337
  if (arguments.length === 1 && isMaybeIdentifier(identifier)) {
1729
- let stableIdentifier = identifierCacheFor(this).peekRecordIdentifier(identifier);
1338
+ let stableIdentifier = this.identifierCache.peekRecordIdentifier(identifier);
1730
1339
  if (stableIdentifier) {
1731
1340
  return internalModelFactoryFor(this).peek(stableIdentifier)?.getRecord() || null;
1732
1341
  }
@@ -1768,9 +1377,7 @@ abstract class CoreStore extends Service {
1768
1377
  @return {Promise} promise
1769
1378
  */
1770
1379
  _reloadRecord(internalModel, options): RSVP.Promise<InternalModel> {
1771
- if (REQUEST_SERVICE) {
1772
- options.isReloading = true;
1773
- }
1380
+ options.isReloading = true;
1774
1381
  let { id, modelName } = internalModel;
1775
1382
  let adapter = this.adapterFor(modelName);
1776
1383
 
@@ -1818,7 +1425,7 @@ abstract class CoreStore extends Service {
1818
1425
  const trueId = ensureStringId(id);
1819
1426
  const resource = { type, id: trueId };
1820
1427
 
1821
- const identifier = identifierCacheFor(this).peekRecordIdentifier(resource);
1428
+ const identifier = this.identifierCache.peekRecordIdentifier(resource);
1822
1429
  const internalModel = identifier && internalModelFactoryFor(this).peek(identifier);
1823
1430
 
1824
1431
  return !!internalModel && internalModel.currentState.isLoaded;
@@ -2017,17 +1624,9 @@ abstract class CoreStore extends Service {
2017
1624
 
2018
1625
  if (internalModel) {
2019
1626
  // short circuit if we are already loading
2020
- if (REQUEST_SERVICE) {
2021
- let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
2022
- if (pendingRequest) {
2023
- return pendingRequest.then(() => internalModel.getRecord());
2024
- }
2025
- } else {
2026
- if (internalModel.currentState.isLoading) {
2027
- return internalModel._promiseProxy.then(() => {
2028
- return internalModel.getRecord();
2029
- });
2030
- }
1627
+ let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
1628
+ if (pendingRequest) {
1629
+ return pendingRequest.then(() => internalModel.getRecord());
2031
1630
  }
2032
1631
  }
2033
1632
 
@@ -2660,33 +2259,32 @@ abstract class CoreStore extends Service {
2660
2259
  @param {Object} options
2661
2260
  */
2662
2261
  scheduleSave(internalModel: InternalModel, resolver: RSVP.Deferred<void>, options): void | RSVP.Promise<void> {
2663
- if (REQUEST_SERVICE) {
2664
- if (internalModel._isRecordFullyDeleted()) {
2665
- resolver.resolve();
2666
- return resolver.promise;
2667
- }
2262
+ if (internalModel._isRecordFullyDeleted()) {
2263
+ resolver.resolve();
2264
+ return resolver.promise;
2265
+ }
2668
2266
 
2669
- internalModel.adapterWillCommit();
2267
+ internalModel.adapterWillCommit();
2670
2268
 
2671
- if (!options) {
2672
- options = {};
2673
- }
2674
- let recordData = internalModel._recordData;
2675
- let operation: 'createRecord' | 'deleteRecord' | 'updateRecord' = 'updateRecord';
2676
-
2677
- // TODO handle missing isNew
2678
- if (recordData.isNew && recordData.isNew()) {
2679
- operation = 'createRecord';
2680
- } else if (recordData.isDeleted && recordData.isDeleted()) {
2681
- operation = 'deleteRecord';
2682
- }
2269
+ if (!options) {
2270
+ options = {};
2271
+ }
2272
+ let recordData = internalModel._recordData;
2273
+ let operation: 'createRecord' | 'deleteRecord' | 'updateRecord' = 'updateRecord';
2274
+
2275
+ // TODO handle missing isNew
2276
+ if (recordData.isNew && recordData.isNew()) {
2277
+ operation = 'createRecord';
2278
+ } else if (recordData.isDeleted && recordData.isDeleted()) {
2279
+ operation = 'deleteRecord';
2280
+ }
2683
2281
 
2684
- options[SaveOp] = operation;
2282
+ options[SaveOp] = operation;
2685
2283
 
2686
- let fetchManagerPromise = this._fetchManager.scheduleSave(internalModel.identifier, options);
2687
- let promise = fetchManagerPromise.then(
2688
- (payload) => {
2689
- /*
2284
+ let fetchManagerPromise = this._fetchManager.scheduleSave(internalModel.identifier, options);
2285
+ let promise = fetchManagerPromise.then(
2286
+ (payload) => {
2287
+ /*
2690
2288
  Note to future spelunkers hoping to optimize.
2691
2289
  We rely on this `run` to create a run loop if needed
2692
2290
  that `store._push` and `store.didSaveRecord` will both share.
@@ -2695,40 +2293,25 @@ abstract class CoreStore extends Service {
2695
2293
  have an outer run loop available still from the first
2696
2294
  call to `store._push`;
2697
2295
  */
2698
- this._backburner.join(() => {
2699
- let data = payload && payload.data;
2700
- this.didSaveRecord(internalModel, { data }, operation);
2701
- if (payload && payload.included) {
2702
- this._push({ data: null, included: payload.included });
2703
- }
2704
- });
2705
- },
2706
- (e) => {
2707
- if (typeof e === 'string') {
2708
- throw e;
2296
+ this._backburner.join(() => {
2297
+ let data = payload && payload.data;
2298
+ this.didSaveRecord(internalModel, { data }, operation);
2299
+ if (payload && payload.included) {
2300
+ this._push({ data: null, included: payload.included });
2709
2301
  }
2710
- const { error, parsedErrors } = e;
2711
- this.recordWasInvalid(internalModel, parsedErrors, error);
2712
- throw error;
2302
+ });
2303
+ },
2304
+ (e) => {
2305
+ if (typeof e === 'string') {
2306
+ throw e;
2713
2307
  }
2714
- );
2715
-
2716
- return promise;
2717
- } else {
2718
- if (internalModel._isRecordFullyDeleted()) {
2719
- resolver.resolve();
2720
- return;
2308
+ const { error, parsedErrors } = e;
2309
+ this.recordWasInvalid(internalModel, parsedErrors, error);
2310
+ throw error;
2721
2311
  }
2312
+ );
2722
2313
 
2723
- let snapshot = internalModel.createSnapshot(options);
2724
- internalModel.adapterWillCommit();
2725
- this._pendingSave.push({
2726
- snapshot: snapshot,
2727
- resolver: resolver,
2728
- });
2729
-
2730
- emberBackburner.scheduleOnce('actions', this, this.flushPendingSave);
2731
- }
2314
+ return promise;
2732
2315
  }
2733
2316
 
2734
2317
  /**
@@ -2739,47 +2322,8 @@ abstract class CoreStore extends Service {
2739
2322
  @private
2740
2323
  */
2741
2324
  flushPendingSave() {
2742
- if (REQUEST_SERVICE) {
2743
- // assert here
2744
- return;
2745
- }
2746
- let pending = this._pendingSave.slice();
2747
- this._pendingSave = [];
2748
-
2749
- for (let i = 0, j = pending.length; i < j; i++) {
2750
- let pendingItem = pending[i];
2751
- let snapshot = pendingItem.snapshot;
2752
- let resolver = pendingItem.resolver;
2753
- // TODO We have to cast due to our reliance on this private property
2754
- // this will be refactored away once we change our pending API to be identifier based
2755
- let internalModel = (snapshot as unknown as PrivateSnapshot)._internalModel;
2756
- let adapter = this.adapterFor(internalModel.modelName);
2757
- let operation;
2758
-
2759
- if (RECORD_DATA_STATE) {
2760
- // TODO move this out of internalModel
2761
- if (internalModel.isNew()) {
2762
- operation = 'createRecord';
2763
- } else if (internalModel.isDeleted()) {
2764
- operation = 'deleteRecord';
2765
- } else {
2766
- operation = 'updateRecord';
2767
- }
2768
- } else {
2769
- if (internalModel.currentState.stateName === 'root.deleted.saved') {
2770
- resolver.resolve();
2771
- continue;
2772
- } else if (internalModel.isNew()) {
2773
- operation = 'createRecord';
2774
- } else if (internalModel.isDeleted()) {
2775
- operation = 'deleteRecord';
2776
- } else {
2777
- operation = 'updateRecord';
2778
- }
2779
- }
2780
-
2781
- resolver.resolve(_commit(adapter, this, operation, snapshot));
2782
- }
2325
+ // assert here
2326
+ return;
2783
2327
  }
2784
2328
 
2785
2329
  /**
@@ -2811,7 +2355,7 @@ abstract class CoreStore extends Service {
2811
2355
  );
2812
2356
  }
2813
2357
 
2814
- const cache = identifierCacheFor(this);
2358
+ const cache = this.identifierCache;
2815
2359
  const identifier = internalModel.identifier;
2816
2360
 
2817
2361
  if (op !== 'deleteRecord' && data) {
@@ -2837,11 +2381,7 @@ abstract class CoreStore extends Service {
2837
2381
  if (DEBUG) {
2838
2382
  assertDestroyingStore(this, 'recordWasInvalid');
2839
2383
  }
2840
- if (RECORD_DATA_ERRORS) {
2841
- internalModel.adapterDidInvalidate(parsedErrors, error);
2842
- } else {
2843
- internalModel.adapterDidInvalidate(parsedErrors);
2844
- }
2384
+ internalModel.adapterDidInvalidate(parsedErrors, error);
2845
2385
  }
2846
2386
 
2847
2387
  /**
@@ -2903,7 +2443,7 @@ abstract class CoreStore extends Service {
2903
2443
  // exclude store.push (root.empty) case
2904
2444
  let identifier = internalModel.identifier;
2905
2445
  if (isUpdate || isLoading) {
2906
- let updatedIdentifier = identifierCacheFor(this).updateRecordIdentifier(identifier, data);
2446
+ let updatedIdentifier = this.identifierCache.updateRecordIdentifier(identifier, data);
2907
2447
 
2908
2448
  if (updatedIdentifier !== identifier) {
2909
2449
  // we encountered a merge of identifiers in which
@@ -3166,30 +2706,17 @@ abstract class CoreStore extends Service {
3166
2706
 
3167
2707
  if (ENV.DS_WARN_ON_UNKNOWN_KEYS) {
3168
2708
  let unknownAttributes, unknownRelationships;
3169
- if (CUSTOM_MODEL_CLASS) {
3170
- let relationships = this.getSchemaDefinitionService().relationshipsDefinitionFor(modelName);
3171
- let attributes = this.getSchemaDefinitionService().attributesDefinitionFor(modelName);
3172
- // Check unknown attributes
3173
- unknownAttributes = Object.keys(data.attributes || {}).filter((key) => {
3174
- return !attributes[key];
3175
- });
3176
-
3177
- // Check unknown relationships
3178
- unknownRelationships = Object.keys(data.relationships || {}).filter((key) => {
3179
- return !relationships[key];
3180
- });
3181
- } else {
3182
- let modelClass = this.modelFor(modelName);
3183
- // Check unknown attributes
3184
- unknownAttributes = Object.keys(data.attributes || {}).filter((key) => {
3185
- return !get(modelClass, 'fields').has(key);
3186
- });
3187
-
3188
- // Check unknown relationships
3189
- unknownRelationships = Object.keys(data.relationships || {}).filter((key) => {
3190
- return !get(modelClass, 'fields').has(key);
3191
- });
3192
- }
2709
+ let relationships = this.getSchemaDefinitionService().relationshipsDefinitionFor(modelName);
2710
+ let attributes = this.getSchemaDefinitionService().attributesDefinitionFor(modelName);
2711
+ // Check unknown attributes
2712
+ unknownAttributes = Object.keys(data.attributes || {}).filter((key) => {
2713
+ return !attributes[key];
2714
+ });
2715
+
2716
+ // Check unknown relationships
2717
+ unknownRelationships = Object.keys(data.relationships || {}).filter((key) => {
2718
+ return !relationships[key];
2719
+ });
3193
2720
  let unknownAttributesMessage = `The payload for '${modelName}' contains these unknown attributes: ${unknownAttributes}. Make sure they've been defined in your model.`;
3194
2721
  warn(unknownAttributesMessage, unknownAttributes.length === 0, {
3195
2722
  id: 'ds.store.unknown-keys-in-payload',
@@ -3319,38 +2846,26 @@ abstract class CoreStore extends Service {
3319
2846
  }
3320
2847
 
3321
2848
  serializeRecord(record: RecordInstance, options?: Dict<unknown>): unknown {
3322
- if (CUSTOM_MODEL_CLASS) {
3323
- let identifier = recordIdentifierFor(record);
3324
- let internalModel = internalModelFactoryFor(this).peek(identifier);
3325
- // TODO we used to check if the record was destroyed here
3326
- return internalModel!.createSnapshot(options).serialize(options);
3327
- }
3328
-
3329
- assert('serializeRecord is only available when CUSTOM_MODEL_CLASS ff is on', false);
2849
+ let identifier = recordIdentifierFor(record);
2850
+ let internalModel = internalModelFactoryFor(this).peek(identifier);
2851
+ // TODO we used to check if the record was destroyed here
2852
+ return internalModel!.createSnapshot(options).serialize(options);
3330
2853
  }
3331
2854
 
3332
2855
  saveRecord(record: RecordInstance, options?: Dict<unknown>): RSVP.Promise<RecordInstance> {
3333
- if (CUSTOM_MODEL_CLASS) {
3334
- let identifier = recordIdentifierFor(record);
3335
- let internalModel = internalModelFactoryFor(this).peek(identifier);
3336
- // TODO we used to check if the record was destroyed here
3337
- // Casting can be removed once REQUEST_SERVICE ff is turned on
3338
- // because a `Record` is provided there will always be a matching internalModel
3339
- return (internalModel!.save(options) as RSVP.Promise<void>).then(() => record);
3340
- }
3341
-
3342
- assert('saveRecord is only available when CUSTOM_MODEL_CLASS ff is on');
2856
+ let identifier = recordIdentifierFor(record);
2857
+ let internalModel = internalModelFactoryFor(this).peek(identifier);
2858
+ // TODO we used to check if the record was destroyed here
2859
+ // Casting can be removed once REQUEST_SERVICE ff is turned on
2860
+ // because a `Record` is provided there will always be a matching internalModel
2861
+ return (internalModel!.save(options) as RSVP.Promise<void>).then(() => record);
3343
2862
  }
3344
2863
 
3345
2864
  relationshipReferenceFor(identifier: RecordIdentifier, key: string): BelongsToReference | HasManyReference {
3346
- if (CUSTOM_MODEL_CLASS) {
3347
- let stableIdentifier = identifierCacheFor(this).getOrCreateRecordIdentifier(identifier);
3348
- let internalModel = internalModelFactoryFor(this).peek(stableIdentifier);
3349
- // TODO we used to check if the record was destroyed here
3350
- return internalModel!.referenceFor(null, key);
3351
- }
3352
-
3353
- assert('relationshipReferenceFor is only available when CUSTOM_MODEL_CLASS ff is on', false);
2865
+ let stableIdentifier = this.identifierCache.getOrCreateRecordIdentifier(identifier);
2866
+ let internalModel = internalModelFactoryFor(this).peek(stableIdentifier);
2867
+ // TODO we used to check if the record was destroyed here
2868
+ return internalModel!.referenceFor(null, key);
3354
2869
  }
3355
2870
 
3356
2871
  /**
@@ -3396,7 +2911,7 @@ abstract class CoreStore extends Service {
3396
2911
  _RecordData = require('@ember-data/record-data/-private').RecordData as RecordDataConstruct;
3397
2912
  }
3398
2913
 
3399
- let identifier = identifierCacheFor(this).getOrCreateRecordIdentifier({
2914
+ let identifier = this.identifierCache.getOrCreateRecordIdentifier({
3400
2915
  type: modelName,
3401
2916
  id,
3402
2917
  lid: clientId,
@@ -3411,7 +2926,7 @@ abstract class CoreStore extends Service {
3411
2926
  * @internal
3412
2927
  */
3413
2928
  __recordDataFor(resource: RecordIdentifier) {
3414
- const identifier = identifierCacheFor(this).getOrCreateRecordIdentifier(resource);
2929
+ const identifier = this.identifierCache.getOrCreateRecordIdentifier(resource);
3415
2930
  return this.recordDataFor(identifier, false);
3416
2931
  }
3417
2932
 
@@ -3529,25 +3044,15 @@ abstract class CoreStore extends Service {
3529
3044
 
3530
3045
  let owner = getOwner(this);
3531
3046
 
3047
+ // name specific adapter
3532
3048
  adapter = owner.lookup(`adapter:${normalizedModelName}`);
3533
-
3534
- // in production this is handled by the re-export
3535
- if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_ADAPTER_PACKAGE && adapter === undefined) {
3536
- if (normalizedModelName === '-json-api') {
3537
- const Adapter = require('@ember-data/adapter/json-api').default;
3538
- owner.register(`adapter:-json-api`, Adapter);
3539
- adapter = owner.lookup(`adapter:-json-api`);
3540
- deprecateTestRegistration('adapter', '-json-api');
3541
- }
3542
- }
3543
-
3544
3049
  if (adapter !== undefined) {
3545
3050
  set(adapter, 'store', this);
3546
3051
  _adapterCache[normalizedModelName] = adapter;
3547
3052
  return adapter;
3548
3053
  }
3549
3054
 
3550
- // no adapter found for the specific model, fallback and check for application adapter
3055
+ // no adapter found for the specific name, fallback and check for application adapter
3551
3056
  adapter = _adapterCache.application || owner.lookup('adapter:application');
3552
3057
  if (adapter !== undefined) {
3553
3058
  set(adapter, 'store', this);
@@ -3556,30 +3061,9 @@ abstract class CoreStore extends Service {
3556
3061
  return adapter;
3557
3062
  }
3558
3063
 
3559
- // no model specific adapter or application adapter, check for an `adapter`
3560
- // property defined on the store
3561
- let adapterName = this.adapter || '-json-api';
3562
- adapter = adapterName ? _adapterCache[adapterName] || owner.lookup(`adapter:${adapterName}`) : undefined;
3563
-
3564
- // in production this is handled by the re-export
3565
- if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_ADAPTER_PACKAGE && adapter === undefined) {
3566
- if (adapterName === '-json-api') {
3567
- const Adapter = require('@ember-data/adapter/json-api').default;
3568
- owner.register(`adapter:-json-api`, Adapter);
3569
- adapter = owner.lookup(`adapter:-json-api`);
3570
- deprecateTestRegistration('adapter', '-json-api');
3571
- }
3572
- }
3573
-
3574
- if (adapter !== undefined) {
3575
- set(adapter, 'store', this);
3576
- _adapterCache[normalizedModelName] = adapter;
3577
- _adapterCache[adapterName] = adapter;
3578
- return adapter;
3579
- }
3580
-
3581
3064
  // final fallback, no model specific adapter, no application adapter, no
3582
3065
  // `adapter` property on store: use json-api adapter
3066
+ // TODO we should likely deprecate this?
3583
3067
  adapter = _adapterCache['-json-api'] || owner.lookup('adapter:-json-api');
3584
3068
  assert(
3585
3069
  `No adapter was found for '${modelName}' and no 'application' adapter was found as a fallback.`,
@@ -3631,30 +3115,8 @@ abstract class CoreStore extends Service {
3631
3115
 
3632
3116
  let owner = getOwner(this);
3633
3117
 
3118
+ // by name
3634
3119
  serializer = owner.lookup(`serializer:${normalizedModelName}`);
3635
-
3636
- if (DEPRECATE_LEGACY_TEST_REGISTRATIONS) {
3637
- // in production this is handled by the re-export
3638
- if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE && serializer === undefined) {
3639
- if (normalizedModelName === '-json-api') {
3640
- const Serializer = require('@ember-data/serializer/json-api').default;
3641
- owner.register(`serializer:-json-api`, Serializer);
3642
- serializer = owner.lookup(`serializer:-json-api`);
3643
- deprecateTestRegistration('serializer', '-json-api');
3644
- } else if (normalizedModelName === '-rest') {
3645
- const Serializer = require('@ember-data/serializer/rest').default;
3646
- owner.register(`serializer:-rest`, Serializer);
3647
- serializer = owner.lookup(`serializer:-rest`);
3648
- deprecateTestRegistration('serializer', '-rest');
3649
- } else if (normalizedModelName === '-default') {
3650
- const Serializer = require('@ember-data/serializer/json').default;
3651
- owner.register(`serializer:-default`, Serializer);
3652
- serializer = owner.lookup(`serializer:-default`);
3653
- serializer && deprecateTestRegistration('serializer', '-default');
3654
- }
3655
- }
3656
- }
3657
-
3658
3120
  if (serializer !== undefined) {
3659
3121
  set(serializer, 'store', this);
3660
3122
  _serializerCache[normalizedModelName] = serializer;
@@ -3670,37 +3132,6 @@ abstract class CoreStore extends Service {
3670
3132
  return serializer;
3671
3133
  }
3672
3134
 
3673
- let serializerName;
3674
-
3675
- if (DEPRECATE_LEGACY_TEST_REGISTRATIONS) {
3676
- // in production this is handled by the re-export
3677
- if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE && serializer === undefined) {
3678
- if (serializerName === '-json-api') {
3679
- const Serializer = require('@ember-data/serializer/json-api').default;
3680
- owner.register(`serializer:-json-api`, Serializer);
3681
- serializer = owner.lookup(`serializer:-json-api`);
3682
- deprecateTestRegistration('serializer', '-json-api');
3683
- } else if (serializerName === '-rest') {
3684
- const Serializer = require('@ember-data/serializer/rest').default;
3685
- owner.register(`serializer:-rest`, Serializer);
3686
- serializer = owner.lookup(`serializer:-rest`);
3687
- deprecateTestRegistration('serializer', '-rest');
3688
- } else if (serializerName === '-default') {
3689
- const Serializer = require('@ember-data/serializer/json').default;
3690
- owner.register(`serializer:-default`, Serializer);
3691
- serializer = owner.lookup(`serializer:-default`);
3692
- serializer && deprecateTestRegistration('serializer', '-default');
3693
- }
3694
- }
3695
-
3696
- if (serializer !== undefined) {
3697
- set(serializer, 'store', this);
3698
- _serializerCache[normalizedModelName] = serializer;
3699
- _serializerCache[serializerName] = serializer;
3700
- return serializer;
3701
- }
3702
- }
3703
-
3704
3135
  assert(
3705
3136
  `No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
3706
3137
  serializer !== undefined
@@ -3738,7 +3169,7 @@ abstract class CoreStore extends Service {
3738
3169
  super.willDestroy();
3739
3170
  this.recordArrayManager.destroy();
3740
3171
 
3741
- identifierCacheFor(this).destroy();
3172
+ this.identifierCache.destroy();
3742
3173
 
3743
3174
  // destroy the graph before unloadAll
3744
3175
  // since then we avoid churning relationships
@@ -3798,155 +3229,23 @@ abstract class CoreStore extends Service {
3798
3229
  }
3799
3230
  }
3800
3231
 
3801
- if (DEPRECATE_DEFAULT_ADAPTER) {
3802
- defineProperty(
3803
- CoreStore.prototype,
3804
- 'defaultAdapter',
3805
- computed('adapter', function () {
3806
- deprecate(
3807
- `store.adapterFor(modelName) resolved the ("${
3808
- this.adapter || '-json-api'
3809
- }") adapter via the deprecated \`store.defaultAdapter\` property.\n\n\tPreviously, applications could define the store's \`adapter\` property which would be used by \`defaultAdapter\` and \`adapterFor\` as a fallback for when an adapter was not found by an exact name match. This behavior is deprecated in favor of explicitly defining an application or type-specific adapter.`,
3810
- false,
3811
- {
3812
- id: 'ember-data:default-adapter',
3813
- until: '4.0',
3814
- url: 'https://deprecations.emberjs.com/ember-data/v3.x/#toc_ember-data-default-adapter',
3815
- for: '@ember-data/store',
3816
- since: {
3817
- available: '3.15',
3818
- enabled: '3.15',
3819
- },
3820
- }
3821
- );
3822
- let adapter = this.adapter || '-json-api';
3823
-
3824
- assert(
3825
- 'You tried to set `adapter` property to an instance of `Adapter`, where it should be a name',
3826
- typeof adapter === 'string'
3827
- );
3828
-
3829
- return this.adapterFor(adapter);
3830
- })
3831
- );
3832
- }
3833
-
3834
3232
  export default CoreStore;
3835
3233
 
3836
- function _commit(adapter, store, operation, snapshot) {
3837
- let internalModel = snapshot._internalModel;
3838
- let modelName = snapshot.modelName;
3839
- let modelClass = store.modelFor(modelName);
3840
- assert(`You tried to update a record but you have no adapter (for ${modelName})`, adapter);
3841
- assert(
3842
- `You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`,
3843
- typeof adapter[operation] === 'function'
3844
- );
3845
-
3846
- let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot));
3847
- let serializer = store.serializerFor(modelName);
3848
- let label = `DS: Extract and notify about ${operation} completion of ${internalModel}`;
3849
-
3850
- promise = guardDestroyedStore(promise, store, label);
3851
- promise = _guard(promise, _bind(_objectIsAlive, internalModel));
3852
-
3853
- return promise.then(
3854
- (adapterPayload) => {
3855
- /*
3856
- Note to future spelunkers hoping to optimize.
3857
- We rely on this `run` to create a run loop if needed
3858
- that `store._push` and `store.didSaveRecord` will both share.
3859
-
3860
- We use `join` because it is often the case that we
3861
- have an outer run loop available still from the first
3862
- call to `store._push`;
3863
- */
3864
- store._backburner.join(() => {
3865
- let payload, data, sideloaded;
3866
- if (adapterPayload) {
3867
- payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation);
3868
- if (payload.included) {
3869
- sideloaded = payload.included;
3870
- }
3871
- data = payload.data;
3872
- }
3873
- store.didSaveRecord(internalModel, { data }, operation);
3874
- // seems risky, but if the tests pass might be fine?
3875
- if (sideloaded) {
3876
- store._push({ data: null, included: sideloaded });
3877
- }
3878
- });
3879
-
3880
- return internalModel;
3881
- },
3882
- function (error) {
3883
- if (error && error.isAdapterError === true && error.code === 'InvalidError') {
3884
- let parsedErrors;
3885
-
3886
- if (typeof serializer.extractErrors === 'function') {
3887
- parsedErrors = serializer.extractErrors(store, modelClass, error, snapshot.id);
3888
- } else {
3889
- parsedErrors = errorsArrayToHash(error.errors);
3890
- }
3891
-
3892
- store.recordWasInvalid(internalModel, parsedErrors, error);
3893
- } else {
3894
- store.recordWasError(internalModel, error);
3895
- }
3896
-
3897
- throw error;
3898
- },
3899
- label
3900
- );
3901
- }
3902
-
3903
3234
  let assertDestroyingStore: Function;
3904
3235
  let assertDestroyedStoreOnly: Function;
3905
3236
 
3906
3237
  if (DEBUG) {
3907
3238
  assertDestroyingStore = function assertDestroyedStore(store, method) {
3908
- if (!store.shouldAssertMethodCallsOnDestroyedStore) {
3909
- deprecate(
3910
- `Attempted to call store.${method}(), but the store instance has already been destroyed.`,
3911
- !(store.isDestroying || store.isDestroyed),
3912
- {
3913
- id: 'ember-data:method-calls-on-destroyed-store',
3914
- until: '3.8',
3915
- for: '@ember-data/store',
3916
- since: {
3917
- available: '3.8',
3918
- enabled: '3.8',
3919
- },
3920
- }
3921
- );
3922
- } else {
3923
- assert(
3924
- `Attempted to call store.${method}(), but the store instance has already been destroyed.`,
3925
- !(store.isDestroying || store.isDestroyed)
3926
- );
3927
- }
3239
+ assert(
3240
+ `Attempted to call store.${method}(), but the store instance has already been destroyed.`,
3241
+ !(store.isDestroying || store.isDestroyed)
3242
+ );
3928
3243
  };
3929
3244
  assertDestroyedStoreOnly = function assertDestroyedStoreOnly(store, method) {
3930
- if (!store.shouldAssertMethodCallsOnDestroyedStore) {
3931
- deprecate(
3932
- `Attempted to call store.${method}(), but the store instance has already been destroyed.`,
3933
- !store.isDestroyed,
3934
- {
3935
- id: 'ember-data:method-calls-on-destroyed-store',
3936
- until: '3.8',
3937
- for: '@ember-data/store',
3938
- since: {
3939
- available: '3.8',
3940
- enabled: '3.8',
3941
- },
3942
- }
3943
- );
3944
- } else {
3945
- assert(
3946
- `Attempted to call store.${method}(), but the store instance has already been destroyed.`,
3947
- !store.isDestroyed
3948
- );
3949
- }
3245
+ assert(
3246
+ `Attempted to call store.${method}(), but the store instance has already been destroyed.`,
3247
+ !store.isDestroyed
3248
+ );
3950
3249
  };
3951
3250
  }
3952
3251
 
@@ -3961,7 +3260,7 @@ if (DEBUG) {
3961
3260
  * @return {boolean}
3962
3261
  */
3963
3262
  function areAllInverseRecordsLoaded(store: CoreStore, resource: JsonApiRelationship): boolean {
3964
- const cache = identifierCacheFor(store);
3263
+ const cache = store.identifierCache;
3965
3264
 
3966
3265
  if (Array.isArray(resource.data)) {
3967
3266
  // treat as collection