@ember-data/store 4.1.0 → 4.2.0-alpha.3

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.
@@ -4,7 +4,7 @@
4
4
  import { getOwner } from '@ember/application';
5
5
  import { A } from '@ember/array';
6
6
  import { assert, deprecate, inspect, warn } from '@ember/debug';
7
- import { computed, defineProperty, get, set } from '@ember/object';
7
+ import { computed, defineProperty, 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,14 +14,8 @@ 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
19
  import {
26
20
  HAS_ADAPTER_PACKAGE,
27
21
  HAS_EMBER_DATA_PACKAGE,
@@ -30,7 +24,6 @@ import {
30
24
  } from '@ember-data/private-build-infra';
31
25
  import {
32
26
  DEPRECATE_DEFAULT_ADAPTER,
33
- DEPRECATE_DEFAULT_SERIALIZER,
34
27
  DEPRECATE_LEGACY_TEST_REGISTRATIONS,
35
28
  } from '@ember-data/private-build-infra/deprecations';
36
29
  import type {
@@ -69,7 +62,6 @@ import constructResource from '../utils/construct-resource';
69
62
  import promiseRecord from '../utils/promise-record';
70
63
  import edBackburner from './backburner';
71
64
  import coerceId, { ensureStringId } from './coerce-id';
72
- import { errorsArrayToHash } from './errors-utils';
73
65
  import FetchManager, { SaveOp } from './fetch-manager';
74
66
  import type InternalModel from './model/internal-model';
75
67
  import {
@@ -87,8 +79,7 @@ import NotificationManager from './record-notification-manager';
87
79
  import type { BelongsToReference, HasManyReference } from './references';
88
80
  import { RecordReference } from './references';
89
81
  import type RequestCache from './request-cache';
90
- import type { default as Snapshot, PrivateSnapshot } from './snapshot';
91
- import { _bind, _guard, _objectIsAlive, guardDestroyedStore } from './store/common';
82
+ import type { default as Snapshot } from './snapshot';
92
83
  import { _find, _findAll, _findBelongsTo, _findHasMany, _findMany, _query, _queryRecord } from './store/finders';
93
84
  import {
94
85
  internalModelFactoryFor,
@@ -97,7 +88,6 @@ import {
97
88
  setRecordIdentifier,
98
89
  } from './store/internal-model-factory';
99
90
  import RecordDataStoreWrapper from './store/record-data-store-wrapper';
100
- import { normalizeResponseHelper } from './store/serializer-response';
101
91
 
102
92
  type RecordDataConstruct = typeof RecordDataClass;
103
93
  let _RecordData: RecordDataConstruct | undefined;
@@ -311,13 +301,9 @@ abstract class CoreStore extends Service {
311
301
  constructor() {
312
302
  super(...arguments);
313
303
 
314
- if (REQUEST_SERVICE) {
315
- this._fetchManager = new FetchManager(this);
316
- }
317
- if (CUSTOM_MODEL_CLASS) {
318
- this._notificationManager = new NotificationManager(this);
319
- this.__recordDataFor = this.__recordDataFor.bind(this);
320
- }
304
+ this._fetchManager = new FetchManager(this);
305
+ this._notificationManager = new NotificationManager(this);
306
+ this.__recordDataFor = this.__recordDataFor.bind(this);
321
307
 
322
308
  if (DEBUG) {
323
309
  if (HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE) {
@@ -422,10 +408,7 @@ abstract class CoreStore extends Service {
422
408
  }
423
409
 
424
410
  getRequestStateService(): RequestCache {
425
- if (REQUEST_SERVICE) {
426
- return this._fetchManager.requestCache;
427
- }
428
- assert('RequestService is not available unless the feature flag is on and running on a canary build', false);
411
+ return this._fetchManager.requestCache;
429
412
  }
430
413
 
431
414
  /**
@@ -449,55 +432,51 @@ abstract class CoreStore extends Service {
449
432
  identifier: StableRecordIdentifier,
450
433
  properties?: { [key: string]: any }
451
434
  ) {
452
- if (CUSTOM_MODEL_CLASS) {
453
- // assert here
454
- if (properties !== undefined) {
455
- assert(
456
- `You passed '${properties}' as properties for record creation instead of an object.`,
457
- typeof properties === 'object' && properties !== null
458
- );
435
+ // assert here
436
+ if (properties !== undefined) {
437
+ assert(
438
+ `You passed '${properties}' as properties for record creation instead of an object.`,
439
+ typeof properties === 'object' && properties !== null
440
+ );
459
441
 
460
- if ('id' in properties) {
461
- internalModel.setId(properties.id);
462
- }
442
+ if ('id' in properties) {
443
+ internalModel.setId(properties.id);
444
+ }
463
445
 
464
- // convert relationship Records to RecordDatas before passing to RecordData
465
- let defs = this._relationshipsDefinitionFor(modelName);
466
-
467
- if (defs !== null) {
468
- let keys = Object.keys(properties);
469
- let relationshipValue;
470
-
471
- for (let i = 0; i < keys.length; i++) {
472
- let prop = keys[i];
473
- let def = defs[prop];
474
-
475
- if (def !== undefined) {
476
- if (def.kind === 'hasMany') {
477
- if (DEBUG) {
478
- assertRecordsPassedToHasMany(properties[prop]);
479
- }
480
- relationshipValue = extractRecordDatasFromRecords(properties[prop]);
481
- } else {
482
- relationshipValue = extractRecordDataFromRecord(properties[prop]);
483
- }
446
+ // convert relationship Records to RecordDatas before passing to RecordData
447
+ let defs = this._relationshipsDefinitionFor(modelName);
448
+
449
+ if (defs !== null) {
450
+ let keys = Object.keys(properties);
451
+ let relationshipValue;
452
+
453
+ for (let i = 0; i < keys.length; i++) {
454
+ let prop = keys[i];
455
+ let def = defs[prop];
484
456
 
485
- properties[prop] = relationshipValue;
457
+ if (def !== undefined) {
458
+ if (def.kind === 'hasMany') {
459
+ if (DEBUG) {
460
+ assertRecordsPassedToHasMany(properties[prop]);
461
+ }
462
+ relationshipValue = extractRecordDatasFromRecords(properties[prop]);
463
+ } else {
464
+ relationshipValue = extractRecordDataFromRecord(properties[prop]);
486
465
  }
466
+
467
+ properties[prop] = relationshipValue;
487
468
  }
488
469
  }
489
470
  }
490
-
491
- // TODO guard against initRecordOptions no being there
492
- let createOptions = recordData._initRecordCreateOptions(properties);
493
- //TODO Igor pass a wrapper instead of RD
494
- let record = this.instantiateRecord(identifier, createOptions, this.__recordDataFor, this._notificationManager);
495
- setRecordIdentifier(record, identifier);
496
- //recordToInternalModelMap.set(record, internalModel);
497
- return record;
498
471
  }
499
472
 
500
- assert('should not be here, custom model class ff error', false);
473
+ // TODO guard against initRecordOptions no being there
474
+ let createOptions = recordData._initRecordCreateOptions(properties);
475
+ //TODO Igor pass a wrapper instead of RD
476
+ let record = this.instantiateRecord(identifier, createOptions, this.__recordDataFor, this._notificationManager);
477
+ setRecordIdentifier(record, identifier);
478
+ //recordToInternalModelMap.set(record, internalModel);
479
+ return record;
501
480
  }
502
481
 
503
482
  abstract instantiateRecord(
@@ -535,10 +514,7 @@ abstract class CoreStore extends Service {
535
514
  }
536
515
 
537
516
  getSchemaDefinitionService(): SchemaDefinitionService {
538
- if (CUSTOM_MODEL_CLASS) {
539
- return this._schemaDefinitionService;
540
- }
541
- assert('need to enable CUSTOM_MODEL_CLASS feature flag in order to access SchemaDefinitionService');
517
+ return this._schemaDefinitionService;
542
518
  }
543
519
 
544
520
  // TODO Double check this return value is correct
@@ -716,31 +692,12 @@ abstract class CoreStore extends Service {
716
692
  assertDestroyingStore(this, 'deleteRecord');
717
693
  }
718
694
  this._backburner.join(() => {
719
- if (CUSTOM_MODEL_CLASS) {
720
- let identifier = peekRecordIdentifier(record);
721
- if (identifier) {
722
- let internalModel = internalModelFactoryFor(this).peek(identifier);
723
- if (internalModel) {
724
- internalModel.deleteRecord();
725
- }
726
- } else {
727
- deprecate(
728
- `You passed a non ember-data managed record ${record} to store.deleteRecord. Ember Data store is not meant to manage non store records. This is not supported and will be removed`,
729
- false,
730
- {
731
- id: 'ember-data:delete-record-non-store',
732
- until: '4.0',
733
- for: '@ember-data/store',
734
- since: {
735
- available: '3.28',
736
- enabled: '3.28',
737
- },
738
- }
739
- );
740
- record.deleteRecord();
695
+ let identifier = peekRecordIdentifier(record);
696
+ if (identifier) {
697
+ let internalModel = internalModelFactoryFor(this).peek(identifier);
698
+ if (internalModel) {
699
+ internalModel.deleteRecord();
741
700
  }
742
- } else {
743
- record.deleteRecord();
744
701
  }
745
702
  });
746
703
  }
@@ -765,31 +722,12 @@ abstract class CoreStore extends Service {
765
722
  if (DEBUG) {
766
723
  assertDestroyingStore(this, 'unloadRecord');
767
724
  }
768
- if (CUSTOM_MODEL_CLASS) {
769
- let identifier = peekRecordIdentifier(record);
770
- if (identifier) {
771
- let internalModel = internalModelFactoryFor(this).peek(identifier);
772
- if (internalModel) {
773
- internalModel.unloadRecord();
774
- }
775
- } else {
776
- deprecate(
777
- `You passed a non ember-data managed record ${record} to store.unloadRecord. Ember Data store is not meant to manage non store records. This is not supported and will be removed`,
778
- false,
779
- {
780
- id: 'ember-data:unload-record-non-store',
781
- until: '4.0',
782
- for: '@ember-data/store',
783
- since: {
784
- available: '3.28',
785
- enabled: '3.28',
786
- },
787
- }
788
- );
789
- record.unloadRecord();
725
+ let identifier = peekRecordIdentifier(record);
726
+ if (identifier) {
727
+ let internalModel = internalModelFactoryFor(this).peek(identifier);
728
+ if (internalModel) {
729
+ internalModel.unloadRecord();
790
730
  }
791
- } else {
792
- record.unloadRecord();
793
731
  }
794
732
  }
795
733
 
@@ -1298,19 +1236,12 @@ abstract class CoreStore extends Service {
1298
1236
  return this._scheduleFetch(internalModel, options);
1299
1237
  }
1300
1238
 
1301
- //TODO double check about reloading
1302
- if (!REQUEST_SERVICE) {
1303
- if (internalModel.currentState.isLoading) {
1304
- return internalModel._promiseProxy;
1305
- }
1306
- } else {
1307
- if (internalModel.currentState.isLoading) {
1308
- let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
1309
- if (pendingRequest) {
1310
- return pendingRequest.then(() => Promise.resolve(internalModel));
1311
- }
1312
- return this._scheduleFetch(internalModel, options);
1239
+ if (internalModel.currentState.isLoading) {
1240
+ let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
1241
+ if (pendingRequest) {
1242
+ return pendingRequest.then(() => Promise.resolve(internalModel));
1313
1243
  }
1244
+ return this._scheduleFetch(internalModel, options);
1314
1245
  }
1315
1246
 
1316
1247
  return Promise.resolve(internalModel);
@@ -1416,74 +1347,12 @@ abstract class CoreStore extends Service {
1416
1347
  }
1417
1348
 
1418
1349
  _scheduleFetch(internalModel: InternalModel, options): RSVP.Promise<InternalModel> {
1419
- if (REQUEST_SERVICE) {
1420
- return this._scheduleFetchThroughFetchManager(internalModel, options);
1421
- } else {
1422
- if (internalModel._promiseProxy) {
1423
- return internalModel._promiseProxy;
1424
- }
1425
-
1426
- assertIdentifierHasId(internalModel.identifier);
1427
-
1428
- let { id, modelName } = internalModel;
1429
- let resolver = defer<InternalModel>(`Fetching ${modelName}' with id: ${id}`);
1430
- let pendingFetchItem: PendingFetchItem = {
1431
- internalModel,
1432
- resolver,
1433
- options,
1434
- };
1435
-
1436
- if (DEBUG) {
1437
- if (this.generateStackTracesForTrackedRequests === true) {
1438
- let trace;
1439
-
1440
- try {
1441
- throw new Error(`Trace Origin for scheduled fetch for ${modelName}:${id}.`);
1442
- } catch (e) {
1443
- trace = e;
1444
- }
1445
-
1446
- // enable folks to discover the origin of this findRecord call when
1447
- // debugging. Ideally we would have a tracked queue for requests with
1448
- // labels or local IDs that could be used to merge this trace with
1449
- // the trace made available when we detect an async leak
1450
- pendingFetchItem.trace = trace;
1451
- }
1452
- }
1453
-
1454
- let promise = resolver.promise;
1455
-
1456
- internalModel.send('loadingData', promise);
1457
- if (this._pendingFetch.size === 0) {
1458
- emberBackburner.schedule('actions', this, this.flushAllPendingFetches);
1459
- }
1460
-
1461
- let fetches = this._pendingFetch;
1462
- let pending = fetches.get(modelName);
1463
-
1464
- if (pending === undefined) {
1465
- pending = [];
1466
- fetches.set(modelName, pending);
1467
- }
1468
-
1469
- pending.push(pendingFetchItem);
1470
-
1471
- return promise;
1472
- }
1350
+ return this._scheduleFetchThroughFetchManager(internalModel, options);
1473
1351
  }
1474
1352
 
1475
1353
  flushAllPendingFetches() {
1476
- if (REQUEST_SERVICE) {
1477
- return;
1478
- //assert here
1479
- } else {
1480
- if (this.isDestroyed || this.isDestroying) {
1481
- return;
1482
- }
1483
-
1484
- this._pendingFetch.forEach(this._flushPendingFetchForType, this);
1485
- this._pendingFetch.clear();
1486
- }
1354
+ return;
1355
+ //assert here
1487
1356
  }
1488
1357
 
1489
1358
  _flushPendingFetchForType(pendingFetchItems: PendingFetchItem[], modelName: string) {
@@ -1799,9 +1668,7 @@ abstract class CoreStore extends Service {
1799
1668
  @return {Promise} promise
1800
1669
  */
1801
1670
  _reloadRecord(internalModel, options): RSVP.Promise<InternalModel> {
1802
- if (REQUEST_SERVICE) {
1803
- options.isReloading = true;
1804
- }
1671
+ options.isReloading = true;
1805
1672
  let { id, modelName } = internalModel;
1806
1673
  let adapter = this.adapterFor(modelName);
1807
1674
 
@@ -2048,17 +1915,9 @@ abstract class CoreStore extends Service {
2048
1915
 
2049
1916
  if (internalModel) {
2050
1917
  // short circuit if we are already loading
2051
- if (REQUEST_SERVICE) {
2052
- let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
2053
- if (pendingRequest) {
2054
- return pendingRequest.then(() => internalModel.getRecord());
2055
- }
2056
- } else {
2057
- if (internalModel.currentState.isLoading) {
2058
- return internalModel._promiseProxy.then(() => {
2059
- return internalModel.getRecord();
2060
- });
2061
- }
1918
+ let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
1919
+ if (pendingRequest) {
1920
+ return pendingRequest.then(() => internalModel.getRecord());
2062
1921
  }
2063
1922
  }
2064
1923
 
@@ -2691,33 +2550,32 @@ abstract class CoreStore extends Service {
2691
2550
  @param {Object} options
2692
2551
  */
2693
2552
  scheduleSave(internalModel: InternalModel, resolver: RSVP.Deferred<void>, options): void | RSVP.Promise<void> {
2694
- if (REQUEST_SERVICE) {
2695
- if (internalModel._isRecordFullyDeleted()) {
2696
- resolver.resolve();
2697
- return resolver.promise;
2698
- }
2553
+ if (internalModel._isRecordFullyDeleted()) {
2554
+ resolver.resolve();
2555
+ return resolver.promise;
2556
+ }
2699
2557
 
2700
- internalModel.adapterWillCommit();
2558
+ internalModel.adapterWillCommit();
2701
2559
 
2702
- if (!options) {
2703
- options = {};
2704
- }
2705
- let recordData = internalModel._recordData;
2706
- let operation: 'createRecord' | 'deleteRecord' | 'updateRecord' = 'updateRecord';
2707
-
2708
- // TODO handle missing isNew
2709
- if (recordData.isNew && recordData.isNew()) {
2710
- operation = 'createRecord';
2711
- } else if (recordData.isDeleted && recordData.isDeleted()) {
2712
- operation = 'deleteRecord';
2713
- }
2560
+ if (!options) {
2561
+ options = {};
2562
+ }
2563
+ let recordData = internalModel._recordData;
2564
+ let operation: 'createRecord' | 'deleteRecord' | 'updateRecord' = 'updateRecord';
2714
2565
 
2715
- options[SaveOp] = operation;
2566
+ // TODO handle missing isNew
2567
+ if (recordData.isNew && recordData.isNew()) {
2568
+ operation = 'createRecord';
2569
+ } else if (recordData.isDeleted && recordData.isDeleted()) {
2570
+ operation = 'deleteRecord';
2571
+ }
2572
+
2573
+ options[SaveOp] = operation;
2716
2574
 
2717
- let fetchManagerPromise = this._fetchManager.scheduleSave(internalModel.identifier, options);
2718
- let promise = fetchManagerPromise.then(
2719
- (payload) => {
2720
- /*
2575
+ let fetchManagerPromise = this._fetchManager.scheduleSave(internalModel.identifier, options);
2576
+ let promise = fetchManagerPromise.then(
2577
+ (payload) => {
2578
+ /*
2721
2579
  Note to future spelunkers hoping to optimize.
2722
2580
  We rely on this `run` to create a run loop if needed
2723
2581
  that `store._push` and `store.didSaveRecord` will both share.
@@ -2726,40 +2584,25 @@ abstract class CoreStore extends Service {
2726
2584
  have an outer run loop available still from the first
2727
2585
  call to `store._push`;
2728
2586
  */
2729
- this._backburner.join(() => {
2730
- let data = payload && payload.data;
2731
- this.didSaveRecord(internalModel, { data }, operation);
2732
- if (payload && payload.included) {
2733
- this._push({ data: null, included: payload.included });
2734
- }
2735
- });
2736
- },
2737
- (e) => {
2738
- if (typeof e === 'string') {
2739
- throw e;
2587
+ this._backburner.join(() => {
2588
+ let data = payload && payload.data;
2589
+ this.didSaveRecord(internalModel, { data }, operation);
2590
+ if (payload && payload.included) {
2591
+ this._push({ data: null, included: payload.included });
2740
2592
  }
2741
- const { error, parsedErrors } = e;
2742
- this.recordWasInvalid(internalModel, parsedErrors, error);
2743
- throw error;
2593
+ });
2594
+ },
2595
+ (e) => {
2596
+ if (typeof e === 'string') {
2597
+ throw e;
2744
2598
  }
2745
- );
2746
-
2747
- return promise;
2748
- } else {
2749
- if (internalModel._isRecordFullyDeleted()) {
2750
- resolver.resolve();
2751
- return;
2599
+ const { error, parsedErrors } = e;
2600
+ this.recordWasInvalid(internalModel, parsedErrors, error);
2601
+ throw error;
2752
2602
  }
2603
+ );
2753
2604
 
2754
- let snapshot = internalModel.createSnapshot(options);
2755
- internalModel.adapterWillCommit();
2756
- this._pendingSave.push({
2757
- snapshot: snapshot,
2758
- resolver: resolver,
2759
- });
2760
-
2761
- emberBackburner.scheduleOnce('actions', this, this.flushPendingSave);
2762
- }
2605
+ return promise;
2763
2606
  }
2764
2607
 
2765
2608
  /**
@@ -2770,47 +2613,8 @@ abstract class CoreStore extends Service {
2770
2613
  @private
2771
2614
  */
2772
2615
  flushPendingSave() {
2773
- if (REQUEST_SERVICE) {
2774
- // assert here
2775
- return;
2776
- }
2777
- let pending = this._pendingSave.slice();
2778
- this._pendingSave = [];
2779
-
2780
- for (let i = 0, j = pending.length; i < j; i++) {
2781
- let pendingItem = pending[i];
2782
- let snapshot = pendingItem.snapshot;
2783
- let resolver = pendingItem.resolver;
2784
- // TODO We have to cast due to our reliance on this private property
2785
- // this will be refactored away once we change our pending API to be identifier based
2786
- let internalModel = (snapshot as unknown as PrivateSnapshot)._internalModel;
2787
- let adapter = this.adapterFor(internalModel.modelName);
2788
- let operation;
2789
-
2790
- if (RECORD_DATA_STATE) {
2791
- // TODO move this out of internalModel
2792
- if (internalModel.isNew()) {
2793
- operation = 'createRecord';
2794
- } else if (internalModel.isDeleted()) {
2795
- operation = 'deleteRecord';
2796
- } else {
2797
- operation = 'updateRecord';
2798
- }
2799
- } else {
2800
- if (internalModel.currentState.stateName === 'root.deleted.saved') {
2801
- resolver.resolve();
2802
- continue;
2803
- } else if (internalModel.isNew()) {
2804
- operation = 'createRecord';
2805
- } else if (internalModel.isDeleted()) {
2806
- operation = 'deleteRecord';
2807
- } else {
2808
- operation = 'updateRecord';
2809
- }
2810
- }
2811
-
2812
- resolver.resolve(_commit(adapter, this, operation, snapshot));
2813
- }
2616
+ // assert here
2617
+ return;
2814
2618
  }
2815
2619
 
2816
2620
  /**
@@ -2868,11 +2672,7 @@ abstract class CoreStore extends Service {
2868
2672
  if (DEBUG) {
2869
2673
  assertDestroyingStore(this, 'recordWasInvalid');
2870
2674
  }
2871
- if (RECORD_DATA_ERRORS) {
2872
- internalModel.adapterDidInvalidate(parsedErrors, error);
2873
- } else {
2874
- internalModel.adapterDidInvalidate(parsedErrors);
2875
- }
2675
+ internalModel.adapterDidInvalidate(parsedErrors, error);
2876
2676
  }
2877
2677
 
2878
2678
  /**
@@ -3197,30 +2997,17 @@ abstract class CoreStore extends Service {
3197
2997
 
3198
2998
  if (ENV.DS_WARN_ON_UNKNOWN_KEYS) {
3199
2999
  let unknownAttributes, unknownRelationships;
3200
- if (CUSTOM_MODEL_CLASS) {
3201
- let relationships = this.getSchemaDefinitionService().relationshipsDefinitionFor(modelName);
3202
- let attributes = this.getSchemaDefinitionService().attributesDefinitionFor(modelName);
3203
- // Check unknown attributes
3204
- unknownAttributes = Object.keys(data.attributes || {}).filter((key) => {
3205
- return !attributes[key];
3206
- });
3207
-
3208
- // Check unknown relationships
3209
- unknownRelationships = Object.keys(data.relationships || {}).filter((key) => {
3210
- return !relationships[key];
3211
- });
3212
- } else {
3213
- let modelClass = this.modelFor(modelName);
3214
- // Check unknown attributes
3215
- unknownAttributes = Object.keys(data.attributes || {}).filter((key) => {
3216
- return !get(modelClass, 'fields').has(key);
3217
- });
3218
-
3219
- // Check unknown relationships
3220
- unknownRelationships = Object.keys(data.relationships || {}).filter((key) => {
3221
- return !get(modelClass, 'fields').has(key);
3222
- });
3223
- }
3000
+ let relationships = this.getSchemaDefinitionService().relationshipsDefinitionFor(modelName);
3001
+ let attributes = this.getSchemaDefinitionService().attributesDefinitionFor(modelName);
3002
+ // Check unknown attributes
3003
+ unknownAttributes = Object.keys(data.attributes || {}).filter((key) => {
3004
+ return !attributes[key];
3005
+ });
3006
+
3007
+ // Check unknown relationships
3008
+ unknownRelationships = Object.keys(data.relationships || {}).filter((key) => {
3009
+ return !relationships[key];
3010
+ });
3224
3011
  let unknownAttributesMessage = `The payload for '${modelName}' contains these unknown attributes: ${unknownAttributes}. Make sure they've been defined in your model.`;
3225
3012
  warn(unknownAttributesMessage, unknownAttributes.length === 0, {
3226
3013
  id: 'ds.store.unknown-keys-in-payload',
@@ -3350,38 +3137,26 @@ abstract class CoreStore extends Service {
3350
3137
  }
3351
3138
 
3352
3139
  serializeRecord(record: RecordInstance, options?: Dict<unknown>): unknown {
3353
- if (CUSTOM_MODEL_CLASS) {
3354
- let identifier = recordIdentifierFor(record);
3355
- let internalModel = internalModelFactoryFor(this).peek(identifier);
3356
- // TODO we used to check if the record was destroyed here
3357
- return internalModel!.createSnapshot(options).serialize(options);
3358
- }
3359
-
3360
- assert('serializeRecord is only available when CUSTOM_MODEL_CLASS ff is on', false);
3140
+ let identifier = recordIdentifierFor(record);
3141
+ let internalModel = internalModelFactoryFor(this).peek(identifier);
3142
+ // TODO we used to check if the record was destroyed here
3143
+ return internalModel!.createSnapshot(options).serialize(options);
3361
3144
  }
3362
3145
 
3363
3146
  saveRecord(record: RecordInstance, options?: Dict<unknown>): RSVP.Promise<RecordInstance> {
3364
- if (CUSTOM_MODEL_CLASS) {
3365
- let identifier = recordIdentifierFor(record);
3366
- let internalModel = internalModelFactoryFor(this).peek(identifier);
3367
- // TODO we used to check if the record was destroyed here
3368
- // Casting can be removed once REQUEST_SERVICE ff is turned on
3369
- // because a `Record` is provided there will always be a matching internalModel
3370
- return (internalModel!.save(options) as RSVP.Promise<void>).then(() => record);
3371
- }
3372
-
3373
- assert('saveRecord is only available when CUSTOM_MODEL_CLASS ff is on');
3147
+ let identifier = recordIdentifierFor(record);
3148
+ let internalModel = internalModelFactoryFor(this).peek(identifier);
3149
+ // TODO we used to check if the record was destroyed here
3150
+ // Casting can be removed once REQUEST_SERVICE ff is turned on
3151
+ // because a `Record` is provided there will always be a matching internalModel
3152
+ return (internalModel!.save(options) as RSVP.Promise<void>).then(() => record);
3374
3153
  }
3375
3154
 
3376
3155
  relationshipReferenceFor(identifier: RecordIdentifier, key: string): BelongsToReference | HasManyReference {
3377
- if (CUSTOM_MODEL_CLASS) {
3378
- let stableIdentifier = identifierCacheFor(this).getOrCreateRecordIdentifier(identifier);
3379
- let internalModel = internalModelFactoryFor(this).peek(stableIdentifier);
3380
- // TODO we used to check if the record was destroyed here
3381
- return internalModel!.referenceFor(null, key);
3382
- }
3383
-
3384
- assert('relationshipReferenceFor is only available when CUSTOM_MODEL_CLASS ff is on', false);
3156
+ let stableIdentifier = identifierCacheFor(this).getOrCreateRecordIdentifier(identifier);
3157
+ let internalModel = internalModelFactoryFor(this).peek(stableIdentifier);
3158
+ // TODO we used to check if the record was destroyed here
3159
+ return internalModel!.referenceFor(null, key);
3385
3160
  }
3386
3161
 
3387
3162
  /**
@@ -3635,10 +3410,6 @@ abstract class CoreStore extends Service {
3635
3410
  for an `App.ApplicationSerializer` (the default serializer for
3636
3411
  your entire application).
3637
3412
 
3638
- if no `App.ApplicationSerializer` is found, it will attempt
3639
- to get the `defaultSerializer` from the `PersonAdapter`
3640
- (`adapterFor('person')`).
3641
-
3642
3413
  If a serializer cannot be found on the adapter, it will fall back
3643
3414
  to an instance of `JSONSerializer`.
3644
3415
 
@@ -3706,31 +3477,6 @@ abstract class CoreStore extends Service {
3706
3477
  }
3707
3478
 
3708
3479
  let serializerName;
3709
- if (DEPRECATE_DEFAULT_SERIALIZER) {
3710
- // no model specific serializer or application serializer, check for the `defaultSerializer`
3711
- // property defined on the adapter
3712
- let adapter = this.adapterFor(modelName);
3713
- serializerName = get(adapter, 'defaultSerializer');
3714
-
3715
- deprecate(
3716
- `store.serializerFor("${modelName}") resolved the "${serializerName}" serializer via the deprecated \`adapter.defaultSerializer\` property.\n\n\tPreviously, if no application or type-specific serializer was specified, the store would attempt to lookup a serializer via the \`defaultSerializer\` property on the type's adapter. This behavior is deprecated in favor of explicitly defining a type-specific serializer or application serializer`,
3717
- !serializerName,
3718
- {
3719
- id: 'ember-data:default-serializer',
3720
- until: '4.0',
3721
- url: 'https://deprecations.emberjs.com/ember-data/v3.x/#toc_ember-data-default-serializers',
3722
- for: '@ember-data/store',
3723
- since: {
3724
- available: '3.15',
3725
- enabled: '3.15',
3726
- },
3727
- }
3728
- );
3729
-
3730
- serializer = serializerName
3731
- ? _serializerCache[serializerName] || owner.lookup(`serializer:${serializerName}`)
3732
- : undefined;
3733
- }
3734
3480
 
3735
3481
  if (DEPRECATE_LEGACY_TEST_REGISTRATIONS) {
3736
3482
  // in production this is handled by the re-export
@@ -3761,49 +3507,10 @@ abstract class CoreStore extends Service {
3761
3507
  }
3762
3508
  }
3763
3509
 
3764
- if (DEPRECATE_DEFAULT_SERIALIZER) {
3765
- // final fallback, no model specific serializer, no application serializer, no
3766
- // `serializer` property on store: use the convenience JSONSerializer
3767
- serializer = _serializerCache['-default'] || owner.lookup('serializer:-default');
3768
- if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE && serializer === undefined) {
3769
- const JSONSerializer = require('@ember-data/serializer/json').default;
3770
- owner.register('serializer:-default', JSONSerializer);
3771
- serializer = owner.lookup('serializer:-default');
3772
-
3773
- serializer && deprecateTestRegistration('serializer', '-default');
3774
- }
3775
-
3776
- deprecate(
3777
- `store.serializerFor("${modelName}") resolved the "-default" serializer via the deprecated "-default" lookup fallback.\n\n\tPreviously, when no type-specific serializer, application serializer, or adapter.defaultSerializer had been defined by the app, the "-default" serializer would be used which defaulted to the \`JSONSerializer\`. This behavior is deprecated in favor of explicitly defining an application or type-specific serializer`,
3778
- !serializer,
3779
- {
3780
- id: 'ember-data:default-serializer',
3781
- until: '4.0',
3782
- url: 'https://deprecations.emberjs.com/ember-data/v3.x/#toc_ember-data-default-serializers',
3783
- for: '@ember-data/store',
3784
- since: {
3785
- available: '3.15',
3786
- enabled: '3.15',
3787
- },
3788
- }
3789
- );
3790
-
3791
- assert(
3792
- `No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
3793
- serializer !== undefined
3794
- );
3795
-
3796
- set(serializer, 'store', this);
3797
- _serializerCache[normalizedModelName] = serializer;
3798
- _serializerCache['-default'] = serializer;
3799
-
3800
- return serializer;
3801
- } else {
3802
- assert(
3803
- `No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
3804
- serializer !== undefined
3805
- );
3806
- }
3510
+ assert(
3511
+ `No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
3512
+ serializer !== undefined
3513
+ );
3807
3514
  }
3808
3515
 
3809
3516
  destroy() {
@@ -3932,73 +3639,6 @@ if (DEPRECATE_DEFAULT_ADAPTER) {
3932
3639
 
3933
3640
  export default CoreStore;
3934
3641
 
3935
- function _commit(adapter, store, operation, snapshot) {
3936
- let internalModel = snapshot._internalModel;
3937
- let modelName = snapshot.modelName;
3938
- let modelClass = store.modelFor(modelName);
3939
- assert(`You tried to update a record but you have no adapter (for ${modelName})`, adapter);
3940
- assert(
3941
- `You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`,
3942
- typeof adapter[operation] === 'function'
3943
- );
3944
-
3945
- let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot));
3946
- let serializer = store.serializerFor(modelName);
3947
- let label = `DS: Extract and notify about ${operation} completion of ${internalModel}`;
3948
-
3949
- promise = guardDestroyedStore(promise, store, label);
3950
- promise = _guard(promise, _bind(_objectIsAlive, internalModel));
3951
-
3952
- return promise.then(
3953
- (adapterPayload) => {
3954
- /*
3955
- Note to future spelunkers hoping to optimize.
3956
- We rely on this `run` to create a run loop if needed
3957
- that `store._push` and `store.didSaveRecord` will both share.
3958
-
3959
- We use `join` because it is often the case that we
3960
- have an outer run loop available still from the first
3961
- call to `store._push`;
3962
- */
3963
- store._backburner.join(() => {
3964
- let payload, data, sideloaded;
3965
- if (adapterPayload) {
3966
- payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation);
3967
- if (payload.included) {
3968
- sideloaded = payload.included;
3969
- }
3970
- data = payload.data;
3971
- }
3972
- store.didSaveRecord(internalModel, { data }, operation);
3973
- // seems risky, but if the tests pass might be fine?
3974
- if (sideloaded) {
3975
- store._push({ data: null, included: sideloaded });
3976
- }
3977
- });
3978
-
3979
- return internalModel;
3980
- },
3981
- function (error) {
3982
- if (error && error.isAdapterError === true && error.code === 'InvalidError') {
3983
- let parsedErrors;
3984
-
3985
- if (typeof serializer.extractErrors === 'function') {
3986
- parsedErrors = serializer.extractErrors(store, modelClass, error, snapshot.id);
3987
- } else {
3988
- parsedErrors = errorsArrayToHash(error.errors);
3989
- }
3990
-
3991
- store.recordWasInvalid(internalModel, parsedErrors, error);
3992
- } else {
3993
- store.recordWasError(internalModel, error);
3994
- }
3995
-
3996
- throw error;
3997
- },
3998
- label
3999
- );
4000
- }
4001
-
4002
3642
  let assertDestroyingStore: Function;
4003
3643
  let assertDestroyedStoreOnly: Function;
4004
3644