@ember-data/store 4.2.0-beta.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/-private/identifiers/cache.ts +3 -16
- package/addon/-private/identifiers/is-stable-identifier.ts +2 -2
- package/addon/-private/index.ts +1 -3
- package/addon/-private/system/core-store.ts +192 -958
- package/addon/-private/system/ds-model-store.ts +20 -111
- package/addon/-private/system/fetch-manager.ts +11 -5
- package/addon/-private/system/model/internal-model.ts +92 -345
- package/addon/-private/system/model/shim-model-class.ts +15 -16
- package/addon/-private/system/model/states.js +2 -14
- package/addon/-private/system/record-array-manager.js +21 -70
- package/addon/-private/system/record-arrays/adapter-populated-record-array.js +1 -20
- package/addon/-private/system/record-arrays/record-array.js +1 -8
- package/addon/-private/system/record-data-for.ts +10 -8
- package/addon/-private/system/record-notification-manager.ts +11 -10
- package/addon/-private/system/references/belongs-to.ts +32 -67
- package/addon/-private/system/references/has-many.ts +21 -41
- package/addon/-private/system/references/record.ts +15 -27
- package/addon/-private/system/references/reference.ts +4 -11
- package/addon/-private/system/schema-definition-service.ts +2 -2
- package/addon/-private/system/snapshot.ts +28 -48
- package/addon/-private/system/store/finders.js +2 -96
- package/addon/-private/system/store/internal-model-factory.ts +34 -28
- package/addon/-private/system/store/record-data-store-wrapper.ts +28 -36
- package/addon/-private/system/weak-cache.ts +125 -0
- package/addon/-private/ts-interfaces/fetch-manager.ts +4 -0
- package/addon/-private/ts-interfaces/identifier.ts +2 -2
- package/addon/-private/ts-interfaces/minimum-adapter-interface.ts +0 -1
- package/addon/-private/ts-interfaces/schema-definition-service.ts +2 -2
- package/package.json +16 -16
- 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,
|
|
7
|
-
import {
|
|
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,25 +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,
|
|
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_DEFAULT_SERIALIZER,
|
|
34
|
-
DEPRECATE_LEGACY_TEST_REGISTRATIONS,
|
|
35
|
-
} from '@ember-data/private-build-infra/deprecations';
|
|
19
|
+
import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
|
|
36
20
|
import type {
|
|
37
21
|
BelongsToRelationship,
|
|
38
22
|
ManyRelationship,
|
|
@@ -40,8 +24,7 @@ import type {
|
|
|
40
24
|
} from '@ember-data/record-data/-private';
|
|
41
25
|
import type { RelationshipState } from '@ember-data/record-data/-private/graph/-state';
|
|
42
26
|
|
|
43
|
-
import
|
|
44
|
-
import { identifierCacheFor } from '../identifiers/cache';
|
|
27
|
+
import { IdentifierCache } from '../identifiers/cache';
|
|
45
28
|
import type { DSModel } from '../ts-interfaces/ds-model';
|
|
46
29
|
import type {
|
|
47
30
|
CollectionResourceDocument,
|
|
@@ -69,7 +52,6 @@ import constructResource from '../utils/construct-resource';
|
|
|
69
52
|
import promiseRecord from '../utils/promise-record';
|
|
70
53
|
import edBackburner from './backburner';
|
|
71
54
|
import coerceId, { ensureStringId } from './coerce-id';
|
|
72
|
-
import { errorsArrayToHash } from './errors-utils';
|
|
73
55
|
import FetchManager, { SaveOp } from './fetch-manager';
|
|
74
56
|
import type InternalModel from './model/internal-model';
|
|
75
57
|
import {
|
|
@@ -87,9 +69,7 @@ import NotificationManager from './record-notification-manager';
|
|
|
87
69
|
import type { BelongsToReference, HasManyReference } from './references';
|
|
88
70
|
import { RecordReference } from './references';
|
|
89
71
|
import type RequestCache from './request-cache';
|
|
90
|
-
import
|
|
91
|
-
import { _bind, _guard, _objectIsAlive, guardDestroyedStore } from './store/common';
|
|
92
|
-
import { _find, _findAll, _findBelongsTo, _findHasMany, _findMany, _query, _queryRecord } from './store/finders';
|
|
72
|
+
import { _findAll, _findBelongsTo, _findHasMany, _query, _queryRecord } from './store/finders';
|
|
93
73
|
import {
|
|
94
74
|
internalModelFactoryFor,
|
|
95
75
|
peekRecordIdentifier,
|
|
@@ -97,7 +77,7 @@ import {
|
|
|
97
77
|
setRecordIdentifier,
|
|
98
78
|
} from './store/internal-model-factory';
|
|
99
79
|
import RecordDataStoreWrapper from './store/record-data-store-wrapper';
|
|
100
|
-
import
|
|
80
|
+
import WeakCache from './weak-cache';
|
|
101
81
|
|
|
102
82
|
type RecordDataConstruct = typeof RecordDataClass;
|
|
103
83
|
let _RecordData: RecordDataConstruct | undefined;
|
|
@@ -105,18 +85,8 @@ let _RecordData: RecordDataConstruct | undefined;
|
|
|
105
85
|
const { ENV } = Ember;
|
|
106
86
|
type AsyncTrackingToken = Readonly<{ label: string; trace: Error | string }>;
|
|
107
87
|
type PromiseArray<T> = Promise<T[]>;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
resolver: RSVP.Deferred<InternalModel>;
|
|
111
|
-
options: any;
|
|
112
|
-
trace?: Error;
|
|
113
|
-
};
|
|
114
|
-
type PendingSaveItem = {
|
|
115
|
-
snapshot: Snapshot;
|
|
116
|
-
resolver: RSVP.Deferred<void>;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const RECORD_REFERENCES = new WeakMap<StableRecordIdentifier, RecordReference>();
|
|
88
|
+
|
|
89
|
+
const RECORD_REFERENCES = new WeakCache<StableRecordIdentifier, RecordReference>(DEBUG ? 'reference' : '');
|
|
120
90
|
|
|
121
91
|
function freeze<T>(obj: T): T {
|
|
122
92
|
if (typeof Object.freeze === 'function') {
|
|
@@ -126,26 +96,6 @@ function freeze<T>(obj: T): T {
|
|
|
126
96
|
return obj;
|
|
127
97
|
}
|
|
128
98
|
|
|
129
|
-
function deprecateTestRegistration(factoryType: 'adapter', factoryName: '-json-api'): void;
|
|
130
|
-
function deprecateTestRegistration(factoryType: 'serializer', factoryName: '-json-api' | '-rest' | '-default'): void;
|
|
131
|
-
function deprecateTestRegistration(
|
|
132
|
-
factoryType: 'serializer' | 'adapter',
|
|
133
|
-
factoryName: '-json-api' | '-rest' | '-default'
|
|
134
|
-
): void {
|
|
135
|
-
deprecate(
|
|
136
|
-
`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.`,
|
|
137
|
-
false,
|
|
138
|
-
{
|
|
139
|
-
id: 'ember-data:-legacy-test-registrations',
|
|
140
|
-
until: '3.17',
|
|
141
|
-
for: '@ember-data/store',
|
|
142
|
-
since: {
|
|
143
|
-
available: '3.15',
|
|
144
|
-
enabled: '3.15',
|
|
145
|
-
},
|
|
146
|
-
}
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
99
|
/**
|
|
150
100
|
The store contains all of the data for records loaded from the server.
|
|
151
101
|
It is also responsible for creating instances of `Model` that wrap
|
|
@@ -219,9 +169,6 @@ function deprecateTestRegistration(
|
|
|
219
169
|
@public
|
|
220
170
|
@extends Ember.Service
|
|
221
171
|
*/
|
|
222
|
-
interface CoreStore {
|
|
223
|
-
adapter: string;
|
|
224
|
-
}
|
|
225
172
|
|
|
226
173
|
abstract class CoreStore extends Service {
|
|
227
174
|
/**
|
|
@@ -233,6 +180,7 @@ abstract class CoreStore extends Service {
|
|
|
233
180
|
public recordArrayManager: RecordArrayManager = new RecordArrayManager({ store: this });
|
|
234
181
|
|
|
235
182
|
declare _notificationManager: NotificationManager;
|
|
183
|
+
declare identifierCache: IdentifierCache;
|
|
236
184
|
private _adapterCache = Object.create(null);
|
|
237
185
|
private _serializerCache = Object.create(null);
|
|
238
186
|
public _storeWrapper = new RecordDataStoreWrapper(this);
|
|
@@ -244,20 +192,14 @@ abstract class CoreStore extends Service {
|
|
|
244
192
|
These queues are currently controlled by a flush scheduled into
|
|
245
193
|
ember-data's custom backburner instance.
|
|
246
194
|
*/
|
|
247
|
-
// used for coalescing record save requests
|
|
248
|
-
private _pendingSave: PendingSaveItem[] = [];
|
|
249
195
|
// used for coalescing internal model updates
|
|
250
196
|
private _updatedInternalModels: InternalModel[] = [];
|
|
251
197
|
|
|
252
|
-
// used to keep track of all the find requests that need to be coalesced
|
|
253
|
-
private _pendingFetch = new Map<string, PendingFetchItem[]>();
|
|
254
|
-
|
|
255
198
|
declare _fetchManager: FetchManager;
|
|
256
199
|
declare _schemaDefinitionService: SchemaDefinitionService;
|
|
257
200
|
|
|
258
201
|
// DEBUG-only properties
|
|
259
202
|
declare _trackedAsyncRequests: AsyncTrackingToken[];
|
|
260
|
-
shouldAssertMethodCallsOnDestroyedStore: boolean = true;
|
|
261
203
|
shouldTrackAsyncRequests: boolean = false;
|
|
262
204
|
generateStackTracesForTrackedRequests: boolean = false;
|
|
263
205
|
declare _trackAsyncRequestStart: (str: string) => void;
|
|
@@ -311,64 +253,27 @@ abstract class CoreStore extends Service {
|
|
|
311
253
|
constructor() {
|
|
312
254
|
super(...arguments);
|
|
313
255
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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();
|
|
321
275
|
|
|
322
276
|
if (DEBUG) {
|
|
323
|
-
if (HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE) {
|
|
324
|
-
// support for legacy moduleFor style unit tests
|
|
325
|
-
// that did not include transforms in "needs"
|
|
326
|
-
// or which were not set to integration:true
|
|
327
|
-
// that were relying on ember-test-helpers
|
|
328
|
-
// doing an auto-registration of the transform
|
|
329
|
-
// or us doing one
|
|
330
|
-
const Mapping = {
|
|
331
|
-
date: 'DateTransform',
|
|
332
|
-
boolean: 'BooleanTransform',
|
|
333
|
-
number: 'NumberTransform',
|
|
334
|
-
string: 'StringTransform',
|
|
335
|
-
};
|
|
336
|
-
type MapKeys = keyof typeof Mapping;
|
|
337
|
-
const keys = Object.keys(Mapping) as MapKeys[];
|
|
338
|
-
let shouldWarn = false;
|
|
339
|
-
|
|
340
|
-
let owner = getOwner(this);
|
|
341
|
-
keys.forEach((attributeType) => {
|
|
342
|
-
const transformFactory = owner.factoryFor(`transform:${attributeType}`);
|
|
343
|
-
|
|
344
|
-
if (!transformFactory) {
|
|
345
|
-
// we don't deprecate this because the moduleFor style tests with the closed
|
|
346
|
-
// resolver will be deprecated on their own. When that deprecation completes
|
|
347
|
-
// we can drop this.
|
|
348
|
-
const Transform = require(`@ember-data/serializer/-private`)[Mapping[attributeType]];
|
|
349
|
-
owner.register(`transform:${attributeType}`, Transform);
|
|
350
|
-
shouldWarn = true;
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
if (shouldWarn) {
|
|
355
|
-
deprecate(
|
|
356
|
-
`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.`,
|
|
357
|
-
false,
|
|
358
|
-
{
|
|
359
|
-
id: 'ember-data:-legacy-test-registrations',
|
|
360
|
-
until: '3.17',
|
|
361
|
-
for: '@ember-data/store',
|
|
362
|
-
since: {
|
|
363
|
-
available: '3.15',
|
|
364
|
-
enabled: '3.15',
|
|
365
|
-
},
|
|
366
|
-
}
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
this.shouldAssertMethodCallsOnDestroyedStore = this.shouldAssertMethodCallsOnDestroyedStore || false;
|
|
372
277
|
if (this.shouldTrackAsyncRequests === undefined) {
|
|
373
278
|
this.shouldTrackAsyncRequests = false;
|
|
374
279
|
}
|
|
@@ -378,14 +283,14 @@ abstract class CoreStore extends Service {
|
|
|
378
283
|
|
|
379
284
|
this._trackedAsyncRequests = [];
|
|
380
285
|
this._trackAsyncRequestStart = (label) => {
|
|
381
|
-
let trace =
|
|
286
|
+
let trace: string | Error =
|
|
382
287
|
'set `store.generateStackTracesForTrackedRequests = true;` to get a detailed trace for where this request originated';
|
|
383
288
|
|
|
384
289
|
if (this.generateStackTracesForTrackedRequests) {
|
|
385
290
|
try {
|
|
386
291
|
throw new Error(`EmberData TrackedRequest: ${label}`);
|
|
387
292
|
} catch (e) {
|
|
388
|
-
trace = e;
|
|
293
|
+
trace = e as Error;
|
|
389
294
|
}
|
|
390
295
|
}
|
|
391
296
|
|
|
@@ -422,24 +327,7 @@ abstract class CoreStore extends Service {
|
|
|
422
327
|
}
|
|
423
328
|
|
|
424
329
|
getRequestStateService(): RequestCache {
|
|
425
|
-
|
|
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);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Provides access to the IdentifierCache instance
|
|
433
|
-
* for this store.
|
|
434
|
-
*
|
|
435
|
-
* The IdentifierCache can be used to generate or
|
|
436
|
-
* retrieve a stable unique identifier for any resource.
|
|
437
|
-
*
|
|
438
|
-
* @property {IdentifierCache} identifierCache
|
|
439
|
-
* @public
|
|
440
|
-
*/
|
|
441
|
-
get identifierCache(): IdentifierCache {
|
|
442
|
-
return identifierCacheFor(this);
|
|
330
|
+
return this._fetchManager.requestCache;
|
|
443
331
|
}
|
|
444
332
|
|
|
445
333
|
_instantiateRecord(
|
|
@@ -449,55 +337,51 @@ abstract class CoreStore extends Service {
|
|
|
449
337
|
identifier: StableRecordIdentifier,
|
|
450
338
|
properties?: { [key: string]: any }
|
|
451
339
|
) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
);
|
|
459
|
-
|
|
460
|
-
if ('id' in properties) {
|
|
461
|
-
internalModel.setId(properties.id);
|
|
462
|
-
}
|
|
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
|
+
);
|
|
463
346
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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
|
-
}
|
|
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 });
|
|
484
353
|
|
|
485
|
-
|
|
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];
|
|
361
|
+
|
|
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]);
|
|
486
370
|
}
|
|
371
|
+
|
|
372
|
+
properties[prop] = relationshipValue;
|
|
487
373
|
}
|
|
488
374
|
}
|
|
489
375
|
}
|
|
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
376
|
}
|
|
499
377
|
|
|
500
|
-
|
|
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;
|
|
501
385
|
}
|
|
502
386
|
|
|
503
387
|
abstract instantiateRecord(
|
|
@@ -514,20 +398,12 @@ abstract class CoreStore extends Service {
|
|
|
514
398
|
}
|
|
515
399
|
|
|
516
400
|
// FeatureFlagged in the DSModelStore claas
|
|
517
|
-
_attributesDefinitionFor(
|
|
518
|
-
|
|
519
|
-
return this.getSchemaDefinitionService().attributesDefinitionFor(identifier);
|
|
520
|
-
} else {
|
|
521
|
-
return this.getSchemaDefinitionService().attributesDefinitionFor(modelName);
|
|
522
|
-
}
|
|
401
|
+
_attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
|
|
402
|
+
return this.getSchemaDefinitionService().attributesDefinitionFor(identifier);
|
|
523
403
|
}
|
|
524
404
|
|
|
525
|
-
_relationshipsDefinitionFor(
|
|
526
|
-
|
|
527
|
-
return this.getSchemaDefinitionService().relationshipsDefinitionFor(identifier);
|
|
528
|
-
} else {
|
|
529
|
-
return this.getSchemaDefinitionService().relationshipsDefinitionFor(modelName);
|
|
530
|
-
}
|
|
405
|
+
_relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }) {
|
|
406
|
+
return this.getSchemaDefinitionService().relationshipsDefinitionFor(identifier);
|
|
531
407
|
}
|
|
532
408
|
|
|
533
409
|
registerSchemaDefinitionService(schema: SchemaDefinitionService) {
|
|
@@ -535,15 +411,12 @@ abstract class CoreStore extends Service {
|
|
|
535
411
|
}
|
|
536
412
|
|
|
537
413
|
getSchemaDefinitionService(): SchemaDefinitionService {
|
|
538
|
-
|
|
539
|
-
return this._schemaDefinitionService;
|
|
540
|
-
}
|
|
541
|
-
assert('need to enable CUSTOM_MODEL_CLASS feature flag in order to access SchemaDefinitionService');
|
|
414
|
+
return this._schemaDefinitionService;
|
|
542
415
|
}
|
|
543
416
|
|
|
544
417
|
// TODO Double check this return value is correct
|
|
545
418
|
_relationshipMetaFor(modelName: string, id: string | null, key: string) {
|
|
546
|
-
return this._relationshipsDefinitionFor(modelName)[key];
|
|
419
|
+
return this._relationshipsDefinitionFor({ type: modelName })[key];
|
|
547
420
|
}
|
|
548
421
|
|
|
549
422
|
/**
|
|
@@ -716,16 +589,12 @@ abstract class CoreStore extends Service {
|
|
|
716
589
|
assertDestroyingStore(this, 'deleteRecord');
|
|
717
590
|
}
|
|
718
591
|
this._backburner.join(() => {
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
internalModel.deleteRecord();
|
|
725
|
-
}
|
|
592
|
+
let identifier = peekRecordIdentifier(record);
|
|
593
|
+
if (identifier) {
|
|
594
|
+
let internalModel = internalModelFactoryFor(this).peek(identifier);
|
|
595
|
+
if (internalModel) {
|
|
596
|
+
internalModel.deleteRecord();
|
|
726
597
|
}
|
|
727
|
-
} else {
|
|
728
|
-
record.deleteRecord();
|
|
729
598
|
}
|
|
730
599
|
});
|
|
731
600
|
}
|
|
@@ -750,16 +619,12 @@ abstract class CoreStore extends Service {
|
|
|
750
619
|
if (DEBUG) {
|
|
751
620
|
assertDestroyingStore(this, 'unloadRecord');
|
|
752
621
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
internalModel.unloadRecord();
|
|
759
|
-
}
|
|
622
|
+
let identifier = peekRecordIdentifier(record);
|
|
623
|
+
if (identifier) {
|
|
624
|
+
let internalModel = internalModelFactoryFor(this).peek(identifier);
|
|
625
|
+
if (internalModel) {
|
|
626
|
+
internalModel.unloadRecord();
|
|
760
627
|
}
|
|
761
|
-
} else {
|
|
762
|
-
record.unloadRecord();
|
|
763
628
|
}
|
|
764
629
|
}
|
|
765
630
|
|
|
@@ -1248,7 +1113,7 @@ abstract class CoreStore extends Service {
|
|
|
1248
1113
|
return Promise.resolve(internalModel);
|
|
1249
1114
|
}
|
|
1250
1115
|
|
|
1251
|
-
_findByInternalModel(internalModel, options:
|
|
1116
|
+
_findByInternalModel(internalModel: InternalModel, options: FindOptions = {}) {
|
|
1252
1117
|
if (options.preload) {
|
|
1253
1118
|
this._backburner.join(() => {
|
|
1254
1119
|
internalModel.preloadData(options.preload);
|
|
@@ -1263,24 +1128,17 @@ abstract class CoreStore extends Service {
|
|
|
1263
1128
|
);
|
|
1264
1129
|
}
|
|
1265
1130
|
|
|
1266
|
-
_findEmptyInternalModel(internalModel, options) {
|
|
1131
|
+
_findEmptyInternalModel(internalModel: InternalModel, options: FindOptions) {
|
|
1267
1132
|
if (internalModel.currentState.isEmpty) {
|
|
1268
1133
|
return this._scheduleFetch(internalModel, options);
|
|
1269
1134
|
}
|
|
1270
1135
|
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
if (
|
|
1274
|
-
return internalModel
|
|
1275
|
-
}
|
|
1276
|
-
} else {
|
|
1277
|
-
if (internalModel.currentState.isLoading) {
|
|
1278
|
-
let pending = this._fetchManager.getPendingFetch(internalModel.identifier);
|
|
1279
|
-
if (pending) {
|
|
1280
|
-
return pending.then(() => Promise.resolve(internalModel));
|
|
1281
|
-
}
|
|
1282
|
-
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));
|
|
1283
1140
|
}
|
|
1141
|
+
return this._scheduleFetch(internalModel, options);
|
|
1284
1142
|
}
|
|
1285
1143
|
|
|
1286
1144
|
return Promise.resolve(internalModel);
|
|
@@ -1317,29 +1175,6 @@ abstract class CoreStore extends Service {
|
|
|
1317
1175
|
return promiseArray(all(promises).then(A, null, `DS: Store#findByIds of ${normalizedModelName} complete`));
|
|
1318
1176
|
}
|
|
1319
1177
|
|
|
1320
|
-
/**
|
|
1321
|
-
This method is called by `findRecord` if it discovers that a particular
|
|
1322
|
-
type/id pair hasn't been loaded yet to kick off a request to the
|
|
1323
|
-
adapter.
|
|
1324
|
-
|
|
1325
|
-
@method _fetchRecord
|
|
1326
|
-
@private
|
|
1327
|
-
@param {InternalModel} internalModel model
|
|
1328
|
-
@return {Promise} promise
|
|
1329
|
-
*/
|
|
1330
|
-
_fetchRecord(internalModel: InternalModel, options): Promise<InternalModel> {
|
|
1331
|
-
let modelName = internalModel.modelName;
|
|
1332
|
-
let adapter = this.adapterFor(modelName);
|
|
1333
|
-
|
|
1334
|
-
assert(`You tried to find a record but you have no adapter (for ${modelName})`, adapter);
|
|
1335
|
-
assert(
|
|
1336
|
-
`You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`,
|
|
1337
|
-
typeof adapter.findRecord === 'function'
|
|
1338
|
-
);
|
|
1339
|
-
|
|
1340
|
-
return _find(adapter, this, internalModel.modelClass, internalModel.id, internalModel, options);
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
1178
|
_scheduleFetchMany(internalModels, options) {
|
|
1344
1179
|
let fetches = new Array(internalModels.length);
|
|
1345
1180
|
|
|
@@ -1350,7 +1185,7 @@ abstract class CoreStore extends Service {
|
|
|
1350
1185
|
return Promise.all(fetches);
|
|
1351
1186
|
}
|
|
1352
1187
|
|
|
1353
|
-
|
|
1188
|
+
_scheduleFetch(internalModel: InternalModel, options = {}): RSVP.Promise<InternalModel> {
|
|
1354
1189
|
let generateStackTrace = this.generateStackTracesForTrackedRequests;
|
|
1355
1190
|
// TODO remove this once we don't rely on state machine
|
|
1356
1191
|
internalModel.send('loadingData');
|
|
@@ -1385,227 +1220,6 @@ abstract class CoreStore extends Service {
|
|
|
1385
1220
|
);
|
|
1386
1221
|
}
|
|
1387
1222
|
|
|
1388
|
-
_scheduleFetch(internalModel: InternalModel, options): RSVP.Promise<InternalModel> {
|
|
1389
|
-
if (REQUEST_SERVICE) {
|
|
1390
|
-
return this._scheduleFetchThroughFetchManager(internalModel, options);
|
|
1391
|
-
} else {
|
|
1392
|
-
if (internalModel._promiseProxy) {
|
|
1393
|
-
return internalModel._promiseProxy;
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
assertIdentifierHasId(internalModel.identifier);
|
|
1397
|
-
|
|
1398
|
-
let { id, modelName } = internalModel;
|
|
1399
|
-
let resolver = defer<InternalModel>(`Fetching ${modelName}' with id: ${id}`);
|
|
1400
|
-
let pendingFetchItem: PendingFetchItem = {
|
|
1401
|
-
internalModel,
|
|
1402
|
-
resolver,
|
|
1403
|
-
options,
|
|
1404
|
-
};
|
|
1405
|
-
|
|
1406
|
-
if (DEBUG) {
|
|
1407
|
-
if (this.generateStackTracesForTrackedRequests === true) {
|
|
1408
|
-
let trace;
|
|
1409
|
-
|
|
1410
|
-
try {
|
|
1411
|
-
throw new Error(`Trace Origin for scheduled fetch for ${modelName}:${id}.`);
|
|
1412
|
-
} catch (e) {
|
|
1413
|
-
trace = e;
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1416
|
-
// enable folks to discover the origin of this findRecord call when
|
|
1417
|
-
// debugging. Ideally we would have a tracked queue for requests with
|
|
1418
|
-
// labels or local IDs that could be used to merge this trace with
|
|
1419
|
-
// the trace made available when we detect an async leak
|
|
1420
|
-
pendingFetchItem.trace = trace;
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
let promise = resolver.promise;
|
|
1425
|
-
|
|
1426
|
-
internalModel.send('loadingData', promise);
|
|
1427
|
-
if (this._pendingFetch.size === 0) {
|
|
1428
|
-
emberBackburner.schedule('actions', this, this.flushAllPendingFetches);
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
let fetches = this._pendingFetch;
|
|
1432
|
-
let pending = fetches.get(modelName);
|
|
1433
|
-
|
|
1434
|
-
if (pending === undefined) {
|
|
1435
|
-
pending = [];
|
|
1436
|
-
fetches.set(modelName, pending);
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
pending.push(pendingFetchItem);
|
|
1440
|
-
|
|
1441
|
-
return promise;
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
flushAllPendingFetches() {
|
|
1446
|
-
if (REQUEST_SERVICE) {
|
|
1447
|
-
return;
|
|
1448
|
-
//assert here
|
|
1449
|
-
} else {
|
|
1450
|
-
if (this.isDestroyed || this.isDestroying) {
|
|
1451
|
-
return;
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
this._pendingFetch.forEach(this._flushPendingFetchForType, this);
|
|
1455
|
-
this._pendingFetch.clear();
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
|
|
1459
|
-
_flushPendingFetchForType(pendingFetchItems: PendingFetchItem[], modelName: string) {
|
|
1460
|
-
let store = this;
|
|
1461
|
-
let adapter = store.adapterFor(modelName);
|
|
1462
|
-
let shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests;
|
|
1463
|
-
let totalItems = pendingFetchItems.length;
|
|
1464
|
-
let internalModels = new Array(totalItems);
|
|
1465
|
-
let seeking = Object.create(null);
|
|
1466
|
-
|
|
1467
|
-
let optionsMap = new WeakMap();
|
|
1468
|
-
|
|
1469
|
-
for (let i = 0; i < totalItems; i++) {
|
|
1470
|
-
let pendingItem = pendingFetchItems[i];
|
|
1471
|
-
let internalModel = pendingItem.internalModel;
|
|
1472
|
-
internalModels[i] = internalModel;
|
|
1473
|
-
optionsMap.set(internalModel, pendingItem.options);
|
|
1474
|
-
// We can remove this "not null" cast once we have enough typing
|
|
1475
|
-
// to know we are only dealing with ExistingResourceIdentifierObjects
|
|
1476
|
-
seeking[internalModel.id!] = pendingItem;
|
|
1477
|
-
}
|
|
1478
|
-
|
|
1479
|
-
function _fetchRecord(recordResolverPair) {
|
|
1480
|
-
let recordFetch = store._fetchRecord(recordResolverPair.internalModel, recordResolverPair.options);
|
|
1481
|
-
|
|
1482
|
-
recordResolverPair.resolver.resolve(recordFetch);
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
function handleFoundRecords(foundInternalModels: InternalModel[], expectedInternalModels: InternalModel[]) {
|
|
1486
|
-
// resolve found records
|
|
1487
|
-
let found = Object.create(null);
|
|
1488
|
-
for (let i = 0, l = foundInternalModels.length; i < l; i++) {
|
|
1489
|
-
let internalModel = foundInternalModels[i];
|
|
1490
|
-
|
|
1491
|
-
// We can remove this "not null" cast once we have enough typing
|
|
1492
|
-
// to know we are only dealing with ExistingResourceIdentifierObjects
|
|
1493
|
-
let pair = seeking[internalModel.id!];
|
|
1494
|
-
found[internalModel.id!] = internalModel;
|
|
1495
|
-
|
|
1496
|
-
if (pair) {
|
|
1497
|
-
let resolver = pair.resolver;
|
|
1498
|
-
resolver.resolve(internalModel);
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
// reject missing records
|
|
1503
|
-
let missingInternalModels: InternalModel[] = [];
|
|
1504
|
-
|
|
1505
|
-
for (let i = 0, l = expectedInternalModels.length; i < l; i++) {
|
|
1506
|
-
let internalModel = expectedInternalModels[i];
|
|
1507
|
-
|
|
1508
|
-
// We can remove this "not null" cast once we have enough typing
|
|
1509
|
-
// to know we are only dealing with ExistingResourceIdentifierObjects
|
|
1510
|
-
if (!found[internalModel.id!]) {
|
|
1511
|
-
missingInternalModels.push(internalModel);
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
if (missingInternalModels.length) {
|
|
1516
|
-
warn(
|
|
1517
|
-
'Ember Data expected to find records with the following ids in the adapter response but they were missing: [ "' +
|
|
1518
|
-
missingInternalModels.map((r) => r.id).join('", "') +
|
|
1519
|
-
'" ]',
|
|
1520
|
-
false,
|
|
1521
|
-
{
|
|
1522
|
-
id: 'ds.store.missing-records-from-adapter',
|
|
1523
|
-
}
|
|
1524
|
-
);
|
|
1525
|
-
rejectInternalModels(missingInternalModels);
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
function rejectInternalModels(internalModels: InternalModel[], error?: Error) {
|
|
1530
|
-
for (let i = 0, l = internalModels.length; i < l; i++) {
|
|
1531
|
-
let internalModel = internalModels[i];
|
|
1532
|
-
|
|
1533
|
-
// We can remove this "not null" cast once we have enough typing
|
|
1534
|
-
// to know we are only dealing with ExistingResourceIdentifierObjects
|
|
1535
|
-
let pair = seeking[internalModel.id!];
|
|
1536
|
-
|
|
1537
|
-
if (pair) {
|
|
1538
|
-
pair.resolver.reject(
|
|
1539
|
-
error ||
|
|
1540
|
-
new Error(
|
|
1541
|
-
`Expected: '${internalModel}' to be present in the adapter provided payload, but it was not found.`
|
|
1542
|
-
)
|
|
1543
|
-
);
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
if (shouldCoalesce) {
|
|
1549
|
-
// TODO: Improve records => snapshots => records => snapshots
|
|
1550
|
-
//
|
|
1551
|
-
// We want to provide records to all store methods and snapshots to all
|
|
1552
|
-
// adapter methods. To make sure we're doing that we're providing an array
|
|
1553
|
-
// of snapshots to adapter.groupRecordsForFindMany(), which in turn will
|
|
1554
|
-
// return grouped snapshots instead of grouped records.
|
|
1555
|
-
//
|
|
1556
|
-
// But since the _findMany() finder is a store method we need to get the
|
|
1557
|
-
// records from the grouped snapshots even though the _findMany() finder
|
|
1558
|
-
// will once again convert the records to snapshots for adapter.findMany()
|
|
1559
|
-
let snapshots = new Array(totalItems);
|
|
1560
|
-
for (let i = 0; i < totalItems; i++) {
|
|
1561
|
-
let internalModel = internalModels[i];
|
|
1562
|
-
snapshots[i] = internalModel.createSnapshot(optionsMap.get(internalModel));
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
let groups;
|
|
1566
|
-
if (adapter.groupRecordsForFindMany) {
|
|
1567
|
-
groups = adapter.groupRecordsForFindMany(this, snapshots);
|
|
1568
|
-
} else {
|
|
1569
|
-
groups = [snapshots];
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
for (let i = 0, l = groups.length; i < l; i++) {
|
|
1573
|
-
let group = groups[i];
|
|
1574
|
-
let totalInGroup = groups[i].length;
|
|
1575
|
-
let ids = new Array(totalInGroup);
|
|
1576
|
-
let groupedInternalModels = new Array(totalInGroup);
|
|
1577
|
-
|
|
1578
|
-
for (let j = 0; j < totalInGroup; j++) {
|
|
1579
|
-
let internalModel = group[j]._internalModel;
|
|
1580
|
-
|
|
1581
|
-
groupedInternalModels[j] = internalModel;
|
|
1582
|
-
ids[j] = internalModel.id;
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
|
-
if (totalInGroup > 1) {
|
|
1586
|
-
(function (groupedInternalModels) {
|
|
1587
|
-
_findMany(adapter, store, modelName, ids, groupedInternalModels, optionsMap)
|
|
1588
|
-
.then(function (foundInternalModels) {
|
|
1589
|
-
handleFoundRecords(foundInternalModels, groupedInternalModels);
|
|
1590
|
-
})
|
|
1591
|
-
.catch(function (error) {
|
|
1592
|
-
rejectInternalModels(groupedInternalModels, error);
|
|
1593
|
-
});
|
|
1594
|
-
})(groupedInternalModels);
|
|
1595
|
-
} else if (ids.length === 1) {
|
|
1596
|
-
let pair = seeking[groupedInternalModels[0].id];
|
|
1597
|
-
_fetchRecord(pair);
|
|
1598
|
-
} else {
|
|
1599
|
-
assert("You cannot return an empty array from adapter's method groupRecordsForFindMany");
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
} else {
|
|
1603
|
-
for (let i = 0; i < totalItems; i++) {
|
|
1604
|
-
_fetchRecord(pendingFetchItems[i]);
|
|
1605
|
-
}
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
1223
|
/**
|
|
1610
1224
|
Get the reference for the specified record.
|
|
1611
1225
|
|
|
@@ -1663,15 +1277,9 @@ abstract class CoreStore extends Service {
|
|
|
1663
1277
|
isMaybeIdentifier(resourceIdentifier)
|
|
1664
1278
|
);
|
|
1665
1279
|
|
|
1666
|
-
let identifier: StableRecordIdentifier =
|
|
1280
|
+
let identifier: StableRecordIdentifier = this.identifierCache.getOrCreateRecordIdentifier(resourceIdentifier);
|
|
1667
1281
|
if (identifier) {
|
|
1668
|
-
|
|
1669
|
-
return RECORD_REFERENCES.get(identifier);
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
|
-
let reference = new RecordReference(this, identifier);
|
|
1673
|
-
RECORD_REFERENCES.set(identifier, reference);
|
|
1674
|
-
return reference;
|
|
1282
|
+
return RECORD_REFERENCES.lookup(identifier);
|
|
1675
1283
|
}
|
|
1676
1284
|
}
|
|
1677
1285
|
|
|
@@ -1727,7 +1335,7 @@ abstract class CoreStore extends Service {
|
|
|
1727
1335
|
peekRecord(identifier: ResourceIdentifierObject): RecordInstance | null;
|
|
1728
1336
|
peekRecord(identifier: ResourceIdentifierObject | string, id?: string | number): RecordInstance | null {
|
|
1729
1337
|
if (arguments.length === 1 && isMaybeIdentifier(identifier)) {
|
|
1730
|
-
let stableIdentifier =
|
|
1338
|
+
let stableIdentifier = this.identifierCache.peekRecordIdentifier(identifier);
|
|
1731
1339
|
if (stableIdentifier) {
|
|
1732
1340
|
return internalModelFactoryFor(this).peek(stableIdentifier)?.getRecord() || null;
|
|
1733
1341
|
}
|
|
@@ -1769,9 +1377,7 @@ abstract class CoreStore extends Service {
|
|
|
1769
1377
|
@return {Promise} promise
|
|
1770
1378
|
*/
|
|
1771
1379
|
_reloadRecord(internalModel, options): RSVP.Promise<InternalModel> {
|
|
1772
|
-
|
|
1773
|
-
options.isReloading = true;
|
|
1774
|
-
}
|
|
1380
|
+
options.isReloading = true;
|
|
1775
1381
|
let { id, modelName } = internalModel;
|
|
1776
1382
|
let adapter = this.adapterFor(modelName);
|
|
1777
1383
|
|
|
@@ -1819,7 +1425,7 @@ abstract class CoreStore extends Service {
|
|
|
1819
1425
|
const trueId = ensureStringId(id);
|
|
1820
1426
|
const resource = { type, id: trueId };
|
|
1821
1427
|
|
|
1822
|
-
const identifier =
|
|
1428
|
+
const identifier = this.identifierCache.peekRecordIdentifier(resource);
|
|
1823
1429
|
const internalModel = identifier && internalModelFactoryFor(this).peek(identifier);
|
|
1824
1430
|
|
|
1825
1431
|
return !!internalModel && internalModel.currentState.isLoaded;
|
|
@@ -2018,17 +1624,9 @@ abstract class CoreStore extends Service {
|
|
|
2018
1624
|
|
|
2019
1625
|
if (internalModel) {
|
|
2020
1626
|
// short circuit if we are already loading
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
return pendingRequest.then(() => internalModel.getRecord());
|
|
2025
|
-
}
|
|
2026
|
-
} else {
|
|
2027
|
-
if (internalModel.currentState.isLoading) {
|
|
2028
|
-
return internalModel._promiseProxy.then(() => {
|
|
2029
|
-
return internalModel.getRecord();
|
|
2030
|
-
});
|
|
2031
|
-
}
|
|
1627
|
+
let pendingRequest = this._fetchManager.getPendingFetch(internalModel.identifier, options);
|
|
1628
|
+
if (pendingRequest) {
|
|
1629
|
+
return pendingRequest.then(() => internalModel.getRecord());
|
|
2032
1630
|
}
|
|
2033
1631
|
}
|
|
2034
1632
|
|
|
@@ -2051,6 +1649,10 @@ abstract class CoreStore extends Service {
|
|
|
2051
1649
|
return resolve(null);
|
|
2052
1650
|
}
|
|
2053
1651
|
|
|
1652
|
+
if (!internalModel) {
|
|
1653
|
+
assert(`No InternalModel found for ${resource.lid}`, internalModel);
|
|
1654
|
+
}
|
|
1655
|
+
|
|
2054
1656
|
return this._findByInternalModel(internalModel, options);
|
|
2055
1657
|
}
|
|
2056
1658
|
|
|
@@ -2657,33 +2259,32 @@ abstract class CoreStore extends Service {
|
|
|
2657
2259
|
@param {Object} options
|
|
2658
2260
|
*/
|
|
2659
2261
|
scheduleSave(internalModel: InternalModel, resolver: RSVP.Deferred<void>, options): void | RSVP.Promise<void> {
|
|
2660
|
-
if (
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
}
|
|
2262
|
+
if (internalModel._isRecordFullyDeleted()) {
|
|
2263
|
+
resolver.resolve();
|
|
2264
|
+
return resolver.promise;
|
|
2265
|
+
}
|
|
2665
2266
|
|
|
2666
|
-
|
|
2267
|
+
internalModel.adapterWillCommit();
|
|
2667
2268
|
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
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
|
+
}
|
|
2680
2281
|
|
|
2681
|
-
|
|
2282
|
+
options[SaveOp] = operation;
|
|
2682
2283
|
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2284
|
+
let fetchManagerPromise = this._fetchManager.scheduleSave(internalModel.identifier, options);
|
|
2285
|
+
let promise = fetchManagerPromise.then(
|
|
2286
|
+
(payload) => {
|
|
2287
|
+
/*
|
|
2687
2288
|
Note to future spelunkers hoping to optimize.
|
|
2688
2289
|
We rely on this `run` to create a run loop if needed
|
|
2689
2290
|
that `store._push` and `store.didSaveRecord` will both share.
|
|
@@ -2692,40 +2293,25 @@ abstract class CoreStore extends Service {
|
|
|
2692
2293
|
have an outer run loop available still from the first
|
|
2693
2294
|
call to `store._push`;
|
|
2694
2295
|
*/
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
}
|
|
2701
|
-
});
|
|
2702
|
-
},
|
|
2703
|
-
(e) => {
|
|
2704
|
-
if (typeof e === 'string') {
|
|
2705
|
-
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 });
|
|
2706
2301
|
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2302
|
+
});
|
|
2303
|
+
},
|
|
2304
|
+
(e) => {
|
|
2305
|
+
if (typeof e === 'string') {
|
|
2306
|
+
throw e;
|
|
2710
2307
|
}
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
} else {
|
|
2715
|
-
if (internalModel._isRecordFullyDeleted()) {
|
|
2716
|
-
resolver.resolve();
|
|
2717
|
-
return;
|
|
2308
|
+
const { error, parsedErrors } = e;
|
|
2309
|
+
this.recordWasInvalid(internalModel, parsedErrors, error);
|
|
2310
|
+
throw error;
|
|
2718
2311
|
}
|
|
2312
|
+
);
|
|
2719
2313
|
|
|
2720
|
-
|
|
2721
|
-
internalModel.adapterWillCommit();
|
|
2722
|
-
this._pendingSave.push({
|
|
2723
|
-
snapshot: snapshot,
|
|
2724
|
-
resolver: resolver,
|
|
2725
|
-
});
|
|
2726
|
-
|
|
2727
|
-
emberBackburner.scheduleOnce('actions', this, this.flushPendingSave);
|
|
2728
|
-
}
|
|
2314
|
+
return promise;
|
|
2729
2315
|
}
|
|
2730
2316
|
|
|
2731
2317
|
/**
|
|
@@ -2736,47 +2322,8 @@ abstract class CoreStore extends Service {
|
|
|
2736
2322
|
@private
|
|
2737
2323
|
*/
|
|
2738
2324
|
flushPendingSave() {
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
return;
|
|
2742
|
-
}
|
|
2743
|
-
let pending = this._pendingSave.slice();
|
|
2744
|
-
this._pendingSave = [];
|
|
2745
|
-
|
|
2746
|
-
for (let i = 0, j = pending.length; i < j; i++) {
|
|
2747
|
-
let pendingItem = pending[i];
|
|
2748
|
-
let snapshot = pendingItem.snapshot;
|
|
2749
|
-
let resolver = pendingItem.resolver;
|
|
2750
|
-
// TODO We have to cast due to our reliance on this private property
|
|
2751
|
-
// this will be refactored away once we change our pending API to be identifier based
|
|
2752
|
-
let internalModel = (snapshot as unknown as PrivateSnapshot)._internalModel;
|
|
2753
|
-
let adapter = this.adapterFor(internalModel.modelName);
|
|
2754
|
-
let operation;
|
|
2755
|
-
|
|
2756
|
-
if (RECORD_DATA_STATE) {
|
|
2757
|
-
// TODO move this out of internalModel
|
|
2758
|
-
if (internalModel.isNew()) {
|
|
2759
|
-
operation = 'createRecord';
|
|
2760
|
-
} else if (internalModel.isDeleted()) {
|
|
2761
|
-
operation = 'deleteRecord';
|
|
2762
|
-
} else {
|
|
2763
|
-
operation = 'updateRecord';
|
|
2764
|
-
}
|
|
2765
|
-
} else {
|
|
2766
|
-
if (internalModel.currentState.stateName === 'root.deleted.saved') {
|
|
2767
|
-
resolver.resolve();
|
|
2768
|
-
continue;
|
|
2769
|
-
} else if (internalModel.isNew()) {
|
|
2770
|
-
operation = 'createRecord';
|
|
2771
|
-
} else if (internalModel.isDeleted()) {
|
|
2772
|
-
operation = 'deleteRecord';
|
|
2773
|
-
} else {
|
|
2774
|
-
operation = 'updateRecord';
|
|
2775
|
-
}
|
|
2776
|
-
}
|
|
2777
|
-
|
|
2778
|
-
resolver.resolve(_commit(adapter, this, operation, snapshot));
|
|
2779
|
-
}
|
|
2325
|
+
// assert here
|
|
2326
|
+
return;
|
|
2780
2327
|
}
|
|
2781
2328
|
|
|
2782
2329
|
/**
|
|
@@ -2808,7 +2355,7 @@ abstract class CoreStore extends Service {
|
|
|
2808
2355
|
);
|
|
2809
2356
|
}
|
|
2810
2357
|
|
|
2811
|
-
const cache =
|
|
2358
|
+
const cache = this.identifierCache;
|
|
2812
2359
|
const identifier = internalModel.identifier;
|
|
2813
2360
|
|
|
2814
2361
|
if (op !== 'deleteRecord' && data) {
|
|
@@ -2834,11 +2381,7 @@ abstract class CoreStore extends Service {
|
|
|
2834
2381
|
if (DEBUG) {
|
|
2835
2382
|
assertDestroyingStore(this, 'recordWasInvalid');
|
|
2836
2383
|
}
|
|
2837
|
-
|
|
2838
|
-
internalModel.adapterDidInvalidate(parsedErrors, error);
|
|
2839
|
-
} else {
|
|
2840
|
-
internalModel.adapterDidInvalidate(parsedErrors);
|
|
2841
|
-
}
|
|
2384
|
+
internalModel.adapterDidInvalidate(parsedErrors, error);
|
|
2842
2385
|
}
|
|
2843
2386
|
|
|
2844
2387
|
/**
|
|
@@ -2900,7 +2443,7 @@ abstract class CoreStore extends Service {
|
|
|
2900
2443
|
// exclude store.push (root.empty) case
|
|
2901
2444
|
let identifier = internalModel.identifier;
|
|
2902
2445
|
if (isUpdate || isLoading) {
|
|
2903
|
-
let updatedIdentifier =
|
|
2446
|
+
let updatedIdentifier = this.identifierCache.updateRecordIdentifier(identifier, data);
|
|
2904
2447
|
|
|
2905
2448
|
if (updatedIdentifier !== identifier) {
|
|
2906
2449
|
// we encountered a merge of identifiers in which
|
|
@@ -3163,30 +2706,17 @@ abstract class CoreStore extends Service {
|
|
|
3163
2706
|
|
|
3164
2707
|
if (ENV.DS_WARN_ON_UNKNOWN_KEYS) {
|
|
3165
2708
|
let unknownAttributes, unknownRelationships;
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
});
|
|
3178
|
-
} else {
|
|
3179
|
-
let modelClass = this.modelFor(modelName);
|
|
3180
|
-
// Check unknown attributes
|
|
3181
|
-
unknownAttributes = Object.keys(data.attributes || {}).filter((key) => {
|
|
3182
|
-
return !get(modelClass, 'fields').has(key);
|
|
3183
|
-
});
|
|
3184
|
-
|
|
3185
|
-
// Check unknown relationships
|
|
3186
|
-
unknownRelationships = Object.keys(data.relationships || {}).filter((key) => {
|
|
3187
|
-
return !get(modelClass, 'fields').has(key);
|
|
3188
|
-
});
|
|
3189
|
-
}
|
|
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
|
+
});
|
|
3190
2720
|
let unknownAttributesMessage = `The payload for '${modelName}' contains these unknown attributes: ${unknownAttributes}. Make sure they've been defined in your model.`;
|
|
3191
2721
|
warn(unknownAttributesMessage, unknownAttributes.length === 0, {
|
|
3192
2722
|
id: 'ds.store.unknown-keys-in-payload',
|
|
@@ -3316,38 +2846,26 @@ abstract class CoreStore extends Service {
|
|
|
3316
2846
|
}
|
|
3317
2847
|
|
|
3318
2848
|
serializeRecord(record: RecordInstance, options?: Dict<unknown>): unknown {
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
return internalModel!.createSnapshot(options).serialize(options);
|
|
3324
|
-
}
|
|
3325
|
-
|
|
3326
|
-
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);
|
|
3327
2853
|
}
|
|
3328
2854
|
|
|
3329
2855
|
saveRecord(record: RecordInstance, options?: Dict<unknown>): RSVP.Promise<RecordInstance> {
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
return (internalModel!.save(options) as RSVP.Promise<void>).then(() => record);
|
|
3337
|
-
}
|
|
3338
|
-
|
|
3339
|
-
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);
|
|
3340
2862
|
}
|
|
3341
2863
|
|
|
3342
2864
|
relationshipReferenceFor(identifier: RecordIdentifier, key: string): BelongsToReference | HasManyReference {
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
return internalModel!.referenceFor(null, key);
|
|
3348
|
-
}
|
|
3349
|
-
|
|
3350
|
-
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);
|
|
3351
2869
|
}
|
|
3352
2870
|
|
|
3353
2871
|
/**
|
|
@@ -3393,7 +2911,7 @@ abstract class CoreStore extends Service {
|
|
|
3393
2911
|
_RecordData = require('@ember-data/record-data/-private').RecordData as RecordDataConstruct;
|
|
3394
2912
|
}
|
|
3395
2913
|
|
|
3396
|
-
let identifier =
|
|
2914
|
+
let identifier = this.identifierCache.getOrCreateRecordIdentifier({
|
|
3397
2915
|
type: modelName,
|
|
3398
2916
|
id,
|
|
3399
2917
|
lid: clientId,
|
|
@@ -3408,7 +2926,7 @@ abstract class CoreStore extends Service {
|
|
|
3408
2926
|
* @internal
|
|
3409
2927
|
*/
|
|
3410
2928
|
__recordDataFor(resource: RecordIdentifier) {
|
|
3411
|
-
const identifier =
|
|
2929
|
+
const identifier = this.identifierCache.getOrCreateRecordIdentifier(resource);
|
|
3412
2930
|
return this.recordDataFor(identifier, false);
|
|
3413
2931
|
}
|
|
3414
2932
|
|
|
@@ -3526,25 +3044,15 @@ abstract class CoreStore extends Service {
|
|
|
3526
3044
|
|
|
3527
3045
|
let owner = getOwner(this);
|
|
3528
3046
|
|
|
3047
|
+
// name specific adapter
|
|
3529
3048
|
adapter = owner.lookup(`adapter:${normalizedModelName}`);
|
|
3530
|
-
|
|
3531
|
-
// in production this is handled by the re-export
|
|
3532
|
-
if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_ADAPTER_PACKAGE && adapter === undefined) {
|
|
3533
|
-
if (normalizedModelName === '-json-api') {
|
|
3534
|
-
const Adapter = require('@ember-data/adapter/json-api').default;
|
|
3535
|
-
owner.register(`adapter:-json-api`, Adapter);
|
|
3536
|
-
adapter = owner.lookup(`adapter:-json-api`);
|
|
3537
|
-
deprecateTestRegistration('adapter', '-json-api');
|
|
3538
|
-
}
|
|
3539
|
-
}
|
|
3540
|
-
|
|
3541
3049
|
if (adapter !== undefined) {
|
|
3542
3050
|
set(adapter, 'store', this);
|
|
3543
3051
|
_adapterCache[normalizedModelName] = adapter;
|
|
3544
3052
|
return adapter;
|
|
3545
3053
|
}
|
|
3546
3054
|
|
|
3547
|
-
// no adapter found for the specific
|
|
3055
|
+
// no adapter found for the specific name, fallback and check for application adapter
|
|
3548
3056
|
adapter = _adapterCache.application || owner.lookup('adapter:application');
|
|
3549
3057
|
if (adapter !== undefined) {
|
|
3550
3058
|
set(adapter, 'store', this);
|
|
@@ -3553,30 +3061,9 @@ abstract class CoreStore extends Service {
|
|
|
3553
3061
|
return adapter;
|
|
3554
3062
|
}
|
|
3555
3063
|
|
|
3556
|
-
// no model specific adapter or application adapter, check for an `adapter`
|
|
3557
|
-
// property defined on the store
|
|
3558
|
-
let adapterName = this.adapter || '-json-api';
|
|
3559
|
-
adapter = adapterName ? _adapterCache[adapterName] || owner.lookup(`adapter:${adapterName}`) : undefined;
|
|
3560
|
-
|
|
3561
|
-
// in production this is handled by the re-export
|
|
3562
|
-
if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_ADAPTER_PACKAGE && adapter === undefined) {
|
|
3563
|
-
if (adapterName === '-json-api') {
|
|
3564
|
-
const Adapter = require('@ember-data/adapter/json-api').default;
|
|
3565
|
-
owner.register(`adapter:-json-api`, Adapter);
|
|
3566
|
-
adapter = owner.lookup(`adapter:-json-api`);
|
|
3567
|
-
deprecateTestRegistration('adapter', '-json-api');
|
|
3568
|
-
}
|
|
3569
|
-
}
|
|
3570
|
-
|
|
3571
|
-
if (adapter !== undefined) {
|
|
3572
|
-
set(adapter, 'store', this);
|
|
3573
|
-
_adapterCache[normalizedModelName] = adapter;
|
|
3574
|
-
_adapterCache[adapterName] = adapter;
|
|
3575
|
-
return adapter;
|
|
3576
|
-
}
|
|
3577
|
-
|
|
3578
3064
|
// final fallback, no model specific adapter, no application adapter, no
|
|
3579
3065
|
// `adapter` property on store: use json-api adapter
|
|
3066
|
+
// TODO we should likely deprecate this?
|
|
3580
3067
|
adapter = _adapterCache['-json-api'] || owner.lookup('adapter:-json-api');
|
|
3581
3068
|
assert(
|
|
3582
3069
|
`No adapter was found for '${modelName}' and no 'application' adapter was found as a fallback.`,
|
|
@@ -3601,10 +3088,6 @@ abstract class CoreStore extends Service {
|
|
|
3601
3088
|
for an `App.ApplicationSerializer` (the default serializer for
|
|
3602
3089
|
your entire application).
|
|
3603
3090
|
|
|
3604
|
-
if no `App.ApplicationSerializer` is found, it will attempt
|
|
3605
|
-
to get the `defaultSerializer` from the `PersonAdapter`
|
|
3606
|
-
(`adapterFor('person')`).
|
|
3607
|
-
|
|
3608
3091
|
If a serializer cannot be found on the adapter, it will fall back
|
|
3609
3092
|
to an instance of `JSONSerializer`.
|
|
3610
3093
|
|
|
@@ -3632,30 +3115,8 @@ abstract class CoreStore extends Service {
|
|
|
3632
3115
|
|
|
3633
3116
|
let owner = getOwner(this);
|
|
3634
3117
|
|
|
3118
|
+
// by name
|
|
3635
3119
|
serializer = owner.lookup(`serializer:${normalizedModelName}`);
|
|
3636
|
-
|
|
3637
|
-
if (DEPRECATE_LEGACY_TEST_REGISTRATIONS) {
|
|
3638
|
-
// in production this is handled by the re-export
|
|
3639
|
-
if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE && serializer === undefined) {
|
|
3640
|
-
if (normalizedModelName === '-json-api') {
|
|
3641
|
-
const Serializer = require('@ember-data/serializer/json-api').default;
|
|
3642
|
-
owner.register(`serializer:-json-api`, Serializer);
|
|
3643
|
-
serializer = owner.lookup(`serializer:-json-api`);
|
|
3644
|
-
deprecateTestRegistration('serializer', '-json-api');
|
|
3645
|
-
} else if (normalizedModelName === '-rest') {
|
|
3646
|
-
const Serializer = require('@ember-data/serializer/rest').default;
|
|
3647
|
-
owner.register(`serializer:-rest`, Serializer);
|
|
3648
|
-
serializer = owner.lookup(`serializer:-rest`);
|
|
3649
|
-
deprecateTestRegistration('serializer', '-rest');
|
|
3650
|
-
} else if (normalizedModelName === '-default') {
|
|
3651
|
-
const Serializer = require('@ember-data/serializer/json').default;
|
|
3652
|
-
owner.register(`serializer:-default`, Serializer);
|
|
3653
|
-
serializer = owner.lookup(`serializer:-default`);
|
|
3654
|
-
serializer && deprecateTestRegistration('serializer', '-default');
|
|
3655
|
-
}
|
|
3656
|
-
}
|
|
3657
|
-
}
|
|
3658
|
-
|
|
3659
3120
|
if (serializer !== undefined) {
|
|
3660
3121
|
set(serializer, 'store', this);
|
|
3661
3122
|
_serializerCache[normalizedModelName] = serializer;
|
|
@@ -3671,105 +3132,10 @@ abstract class CoreStore extends Service {
|
|
|
3671
3132
|
return serializer;
|
|
3672
3133
|
}
|
|
3673
3134
|
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
let adapter = this.adapterFor(modelName);
|
|
3679
|
-
serializerName = get(adapter, 'defaultSerializer');
|
|
3680
|
-
|
|
3681
|
-
deprecate(
|
|
3682
|
-
`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`,
|
|
3683
|
-
!serializerName,
|
|
3684
|
-
{
|
|
3685
|
-
id: 'ember-data:default-serializer',
|
|
3686
|
-
until: '4.0',
|
|
3687
|
-
url: 'https://deprecations.emberjs.com/ember-data/v3.x/#toc_ember-data-default-serializers',
|
|
3688
|
-
for: '@ember-data/store',
|
|
3689
|
-
since: {
|
|
3690
|
-
available: '3.15',
|
|
3691
|
-
enabled: '3.15',
|
|
3692
|
-
},
|
|
3693
|
-
}
|
|
3694
|
-
);
|
|
3695
|
-
|
|
3696
|
-
serializer = serializerName
|
|
3697
|
-
? _serializerCache[serializerName] || owner.lookup(`serializer:${serializerName}`)
|
|
3698
|
-
: undefined;
|
|
3699
|
-
}
|
|
3700
|
-
|
|
3701
|
-
if (DEPRECATE_LEGACY_TEST_REGISTRATIONS) {
|
|
3702
|
-
// in production this is handled by the re-export
|
|
3703
|
-
if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE && serializer === undefined) {
|
|
3704
|
-
if (serializerName === '-json-api') {
|
|
3705
|
-
const Serializer = require('@ember-data/serializer/json-api').default;
|
|
3706
|
-
owner.register(`serializer:-json-api`, Serializer);
|
|
3707
|
-
serializer = owner.lookup(`serializer:-json-api`);
|
|
3708
|
-
deprecateTestRegistration('serializer', '-json-api');
|
|
3709
|
-
} else if (serializerName === '-rest') {
|
|
3710
|
-
const Serializer = require('@ember-data/serializer/rest').default;
|
|
3711
|
-
owner.register(`serializer:-rest`, Serializer);
|
|
3712
|
-
serializer = owner.lookup(`serializer:-rest`);
|
|
3713
|
-
deprecateTestRegistration('serializer', '-rest');
|
|
3714
|
-
} else if (serializerName === '-default') {
|
|
3715
|
-
const Serializer = require('@ember-data/serializer/json').default;
|
|
3716
|
-
owner.register(`serializer:-default`, Serializer);
|
|
3717
|
-
serializer = owner.lookup(`serializer:-default`);
|
|
3718
|
-
serializer && deprecateTestRegistration('serializer', '-default');
|
|
3719
|
-
}
|
|
3720
|
-
}
|
|
3721
|
-
|
|
3722
|
-
if (serializer !== undefined) {
|
|
3723
|
-
set(serializer, 'store', this);
|
|
3724
|
-
_serializerCache[normalizedModelName] = serializer;
|
|
3725
|
-
_serializerCache[serializerName] = serializer;
|
|
3726
|
-
return serializer;
|
|
3727
|
-
}
|
|
3728
|
-
}
|
|
3729
|
-
|
|
3730
|
-
if (DEPRECATE_DEFAULT_SERIALIZER) {
|
|
3731
|
-
// final fallback, no model specific serializer, no application serializer, no
|
|
3732
|
-
// `serializer` property on store: use the convenience JSONSerializer
|
|
3733
|
-
serializer = _serializerCache['-default'] || owner.lookup('serializer:-default');
|
|
3734
|
-
if (DEBUG && HAS_EMBER_DATA_PACKAGE && HAS_SERIALIZER_PACKAGE && serializer === undefined) {
|
|
3735
|
-
const JSONSerializer = require('@ember-data/serializer/json').default;
|
|
3736
|
-
owner.register('serializer:-default', JSONSerializer);
|
|
3737
|
-
serializer = owner.lookup('serializer:-default');
|
|
3738
|
-
|
|
3739
|
-
serializer && deprecateTestRegistration('serializer', '-default');
|
|
3740
|
-
}
|
|
3741
|
-
|
|
3742
|
-
deprecate(
|
|
3743
|
-
`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`,
|
|
3744
|
-
!serializer,
|
|
3745
|
-
{
|
|
3746
|
-
id: 'ember-data:default-serializer',
|
|
3747
|
-
until: '4.0',
|
|
3748
|
-
url: 'https://deprecations.emberjs.com/ember-data/v3.x/#toc_ember-data-default-serializers',
|
|
3749
|
-
for: '@ember-data/store',
|
|
3750
|
-
since: {
|
|
3751
|
-
available: '3.15',
|
|
3752
|
-
enabled: '3.15',
|
|
3753
|
-
},
|
|
3754
|
-
}
|
|
3755
|
-
);
|
|
3756
|
-
|
|
3757
|
-
assert(
|
|
3758
|
-
`No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
|
|
3759
|
-
serializer !== undefined
|
|
3760
|
-
);
|
|
3761
|
-
|
|
3762
|
-
set(serializer, 'store', this);
|
|
3763
|
-
_serializerCache[normalizedModelName] = serializer;
|
|
3764
|
-
_serializerCache['-default'] = serializer;
|
|
3765
|
-
|
|
3766
|
-
return serializer;
|
|
3767
|
-
} else {
|
|
3768
|
-
assert(
|
|
3769
|
-
`No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
|
|
3770
|
-
serializer !== undefined
|
|
3771
|
-
);
|
|
3772
|
-
}
|
|
3135
|
+
assert(
|
|
3136
|
+
`No serializer was found for '${modelName}' and no 'application' serializer was found as a fallback`,
|
|
3137
|
+
serializer !== undefined
|
|
3138
|
+
);
|
|
3773
3139
|
}
|
|
3774
3140
|
|
|
3775
3141
|
destroy() {
|
|
@@ -3803,7 +3169,7 @@ abstract class CoreStore extends Service {
|
|
|
3803
3169
|
super.willDestroy();
|
|
3804
3170
|
this.recordArrayManager.destroy();
|
|
3805
3171
|
|
|
3806
|
-
|
|
3172
|
+
this.identifierCache.destroy();
|
|
3807
3173
|
|
|
3808
3174
|
// destroy the graph before unloadAll
|
|
3809
3175
|
// since then we avoid churning relationships
|
|
@@ -3863,155 +3229,23 @@ abstract class CoreStore extends Service {
|
|
|
3863
3229
|
}
|
|
3864
3230
|
}
|
|
3865
3231
|
|
|
3866
|
-
if (DEPRECATE_DEFAULT_ADAPTER) {
|
|
3867
|
-
defineProperty(
|
|
3868
|
-
CoreStore.prototype,
|
|
3869
|
-
'defaultAdapter',
|
|
3870
|
-
computed('adapter', function () {
|
|
3871
|
-
deprecate(
|
|
3872
|
-
`store.adapterFor(modelName) resolved the ("${
|
|
3873
|
-
this.adapter || '-json-api'
|
|
3874
|
-
}") 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.`,
|
|
3875
|
-
false,
|
|
3876
|
-
{
|
|
3877
|
-
id: 'ember-data:default-adapter',
|
|
3878
|
-
until: '4.0',
|
|
3879
|
-
url: 'https://deprecations.emberjs.com/ember-data/v3.x/#toc_ember-data-default-adapter',
|
|
3880
|
-
for: '@ember-data/store',
|
|
3881
|
-
since: {
|
|
3882
|
-
available: '3.15',
|
|
3883
|
-
enabled: '3.15',
|
|
3884
|
-
},
|
|
3885
|
-
}
|
|
3886
|
-
);
|
|
3887
|
-
let adapter = this.adapter || '-json-api';
|
|
3888
|
-
|
|
3889
|
-
assert(
|
|
3890
|
-
'You tried to set `adapter` property to an instance of `Adapter`, where it should be a name',
|
|
3891
|
-
typeof adapter === 'string'
|
|
3892
|
-
);
|
|
3893
|
-
|
|
3894
|
-
return this.adapterFor(adapter);
|
|
3895
|
-
})
|
|
3896
|
-
);
|
|
3897
|
-
}
|
|
3898
|
-
|
|
3899
3232
|
export default CoreStore;
|
|
3900
3233
|
|
|
3901
|
-
function _commit(adapter, store, operation, snapshot) {
|
|
3902
|
-
let internalModel = snapshot._internalModel;
|
|
3903
|
-
let modelName = snapshot.modelName;
|
|
3904
|
-
let modelClass = store.modelFor(modelName);
|
|
3905
|
-
assert(`You tried to update a record but you have no adapter (for ${modelName})`, adapter);
|
|
3906
|
-
assert(
|
|
3907
|
-
`You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`,
|
|
3908
|
-
typeof adapter[operation] === 'function'
|
|
3909
|
-
);
|
|
3910
|
-
|
|
3911
|
-
let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot));
|
|
3912
|
-
let serializer = store.serializerFor(modelName);
|
|
3913
|
-
let label = `DS: Extract and notify about ${operation} completion of ${internalModel}`;
|
|
3914
|
-
|
|
3915
|
-
promise = guardDestroyedStore(promise, store, label);
|
|
3916
|
-
promise = _guard(promise, _bind(_objectIsAlive, internalModel));
|
|
3917
|
-
|
|
3918
|
-
return promise.then(
|
|
3919
|
-
(adapterPayload) => {
|
|
3920
|
-
/*
|
|
3921
|
-
Note to future spelunkers hoping to optimize.
|
|
3922
|
-
We rely on this `run` to create a run loop if needed
|
|
3923
|
-
that `store._push` and `store.didSaveRecord` will both share.
|
|
3924
|
-
|
|
3925
|
-
We use `join` because it is often the case that we
|
|
3926
|
-
have an outer run loop available still from the first
|
|
3927
|
-
call to `store._push`;
|
|
3928
|
-
*/
|
|
3929
|
-
store._backburner.join(() => {
|
|
3930
|
-
let payload, data, sideloaded;
|
|
3931
|
-
if (adapterPayload) {
|
|
3932
|
-
payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation);
|
|
3933
|
-
if (payload.included) {
|
|
3934
|
-
sideloaded = payload.included;
|
|
3935
|
-
}
|
|
3936
|
-
data = payload.data;
|
|
3937
|
-
}
|
|
3938
|
-
store.didSaveRecord(internalModel, { data }, operation);
|
|
3939
|
-
// seems risky, but if the tests pass might be fine?
|
|
3940
|
-
if (sideloaded) {
|
|
3941
|
-
store._push({ data: null, included: sideloaded });
|
|
3942
|
-
}
|
|
3943
|
-
});
|
|
3944
|
-
|
|
3945
|
-
return internalModel;
|
|
3946
|
-
},
|
|
3947
|
-
function (error) {
|
|
3948
|
-
if (error && error.isAdapterError === true && error.code === 'InvalidError') {
|
|
3949
|
-
let parsedErrors;
|
|
3950
|
-
|
|
3951
|
-
if (typeof serializer.extractErrors === 'function') {
|
|
3952
|
-
parsedErrors = serializer.extractErrors(store, modelClass, error, snapshot.id);
|
|
3953
|
-
} else {
|
|
3954
|
-
parsedErrors = errorsArrayToHash(error.errors);
|
|
3955
|
-
}
|
|
3956
|
-
|
|
3957
|
-
store.recordWasInvalid(internalModel, parsedErrors, error);
|
|
3958
|
-
} else {
|
|
3959
|
-
store.recordWasError(internalModel, error);
|
|
3960
|
-
}
|
|
3961
|
-
|
|
3962
|
-
throw error;
|
|
3963
|
-
},
|
|
3964
|
-
label
|
|
3965
|
-
);
|
|
3966
|
-
}
|
|
3967
|
-
|
|
3968
3234
|
let assertDestroyingStore: Function;
|
|
3969
3235
|
let assertDestroyedStoreOnly: Function;
|
|
3970
3236
|
|
|
3971
3237
|
if (DEBUG) {
|
|
3972
3238
|
assertDestroyingStore = function assertDestroyedStore(store, method) {
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
{
|
|
3978
|
-
id: 'ember-data:method-calls-on-destroyed-store',
|
|
3979
|
-
until: '3.8',
|
|
3980
|
-
for: '@ember-data/store',
|
|
3981
|
-
since: {
|
|
3982
|
-
available: '3.8',
|
|
3983
|
-
enabled: '3.8',
|
|
3984
|
-
},
|
|
3985
|
-
}
|
|
3986
|
-
);
|
|
3987
|
-
} else {
|
|
3988
|
-
assert(
|
|
3989
|
-
`Attempted to call store.${method}(), but the store instance has already been destroyed.`,
|
|
3990
|
-
!(store.isDestroying || store.isDestroyed)
|
|
3991
|
-
);
|
|
3992
|
-
}
|
|
3239
|
+
assert(
|
|
3240
|
+
`Attempted to call store.${method}(), but the store instance has already been destroyed.`,
|
|
3241
|
+
!(store.isDestroying || store.isDestroyed)
|
|
3242
|
+
);
|
|
3993
3243
|
};
|
|
3994
3244
|
assertDestroyedStoreOnly = function assertDestroyedStoreOnly(store, method) {
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
{
|
|
4000
|
-
id: 'ember-data:method-calls-on-destroyed-store',
|
|
4001
|
-
until: '3.8',
|
|
4002
|
-
for: '@ember-data/store',
|
|
4003
|
-
since: {
|
|
4004
|
-
available: '3.8',
|
|
4005
|
-
enabled: '3.8',
|
|
4006
|
-
},
|
|
4007
|
-
}
|
|
4008
|
-
);
|
|
4009
|
-
} else {
|
|
4010
|
-
assert(
|
|
4011
|
-
`Attempted to call store.${method}(), but the store instance has already been destroyed.`,
|
|
4012
|
-
!store.isDestroyed
|
|
4013
|
-
);
|
|
4014
|
-
}
|
|
3245
|
+
assert(
|
|
3246
|
+
`Attempted to call store.${method}(), but the store instance has already been destroyed.`,
|
|
3247
|
+
!store.isDestroyed
|
|
3248
|
+
);
|
|
4015
3249
|
};
|
|
4016
3250
|
}
|
|
4017
3251
|
|
|
@@ -4026,7 +3260,7 @@ if (DEBUG) {
|
|
|
4026
3260
|
* @return {boolean}
|
|
4027
3261
|
*/
|
|
4028
3262
|
function areAllInverseRecordsLoaded(store: CoreStore, resource: JsonApiRelationship): boolean {
|
|
4029
|
-
const cache =
|
|
3263
|
+
const cache = store.identifierCache;
|
|
4030
3264
|
|
|
4031
3265
|
if (Array.isArray(resource.data)) {
|
|
4032
3266
|
// treat as collection
|