@ember-data/legacy-compat 4.12.0-alpha.11 → 4.12.0-alpha.13
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.js +1 -1
- package/addon/{fetch-manager-2716abb1.js → fetch-manager-1067c70f.js} +537 -112
- package/addon/fetch-manager-1067c70f.js.map +1 -0
- package/addon/index.js +405 -42
- package/addon/index.js.map +1 -1
- package/addon-main.js +7 -31
- package/package.json +15 -4
- package/addon/fetch-manager-2716abb1.js.map +0 -1
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { macroCondition, getOwnConfig,
|
|
1
|
+
import { macroCondition, getOwnConfig, importSync } from '@embroider/macros';
|
|
2
2
|
import { deprecate, assert, warn } from '@ember/debug';
|
|
3
3
|
import { SOURCE, coerceId } from '@ember-data/store/-private';
|
|
4
|
-
import {
|
|
5
|
-
import RSVP, { resolve } from 'rsvp';
|
|
4
|
+
import { createDeferred } from '@ember-data/request';
|
|
6
5
|
/**
|
|
7
6
|
SnapshotRecordArray is not directly instantiable.
|
|
8
7
|
Instances are provided to consuming application's
|
|
@@ -137,9 +136,9 @@ class SnapshotRecordArray {
|
|
|
137
136
|
return this._snapshots;
|
|
138
137
|
}
|
|
139
138
|
const {
|
|
140
|
-
|
|
139
|
+
_fetchManager
|
|
141
140
|
} = this.__store;
|
|
142
|
-
this._snapshots = this._recordArray[SOURCE].map(identifier =>
|
|
141
|
+
this._snapshots = this._recordArray[SOURCE].map(identifier => _fetchManager.createSnapshot(identifier));
|
|
143
142
|
return this._snapshots;
|
|
144
143
|
}
|
|
145
144
|
}
|
|
@@ -175,7 +174,7 @@ function _bind(fn, ...args) {
|
|
|
175
174
|
function _guard(promise, test) {
|
|
176
175
|
let guarded = promise.finally(() => {
|
|
177
176
|
if (!test()) {
|
|
178
|
-
guarded._subscribers.length = 0;
|
|
177
|
+
guarded._subscribers ? guarded._subscribers.length = 0 : null;
|
|
179
178
|
}
|
|
180
179
|
});
|
|
181
180
|
return guarded;
|
|
@@ -183,12 +182,8 @@ function _guard(promise, test) {
|
|
|
183
182
|
function _objectIsAlive(object) {
|
|
184
183
|
return !(object.isDestroyed || object.isDestroying);
|
|
185
184
|
}
|
|
186
|
-
function guardDestroyedStore(promise, store
|
|
187
|
-
|
|
188
|
-
if (isDevelopingApp()) {
|
|
189
|
-
token = store._trackAsyncRequestStart(label);
|
|
190
|
-
}
|
|
191
|
-
let wrapperPromise = resolve(promise, label).then(_v => {
|
|
185
|
+
function guardDestroyedStore(promise, store) {
|
|
186
|
+
return promise.then(_v => {
|
|
192
187
|
if (!_objectIsAlive(store)) {
|
|
193
188
|
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
|
|
194
189
|
deprecate(`A Promise did not resolve by the time the store was destroyed. This will error in a future release.`, false, {
|
|
@@ -202,18 +197,26 @@ function guardDestroyedStore(promise, store, label) {
|
|
|
202
197
|
});
|
|
203
198
|
}
|
|
204
199
|
}
|
|
205
|
-
return
|
|
206
|
-
});
|
|
207
|
-
return _guard(wrapperPromise, () => {
|
|
208
|
-
if (isDevelopingApp()) {
|
|
209
|
-
store._trackAsyncRequestEnd(token);
|
|
210
|
-
}
|
|
211
|
-
return _objectIsAlive(store);
|
|
200
|
+
return _v;
|
|
212
201
|
});
|
|
213
202
|
}
|
|
214
203
|
function assertIdentifierHasId(identifier) {
|
|
215
204
|
assert(`Attempted to schedule a fetch for a record without an id.`, identifier.id !== null);
|
|
216
205
|
}
|
|
206
|
+
function iterateData(data, fn) {
|
|
207
|
+
if (Array.isArray(data)) {
|
|
208
|
+
return data.map(fn);
|
|
209
|
+
} else {
|
|
210
|
+
return fn(data);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function payloadIsNotBlank(adapterPayload) {
|
|
214
|
+
if (Array.isArray(adapterPayload)) {
|
|
215
|
+
return true;
|
|
216
|
+
} else {
|
|
217
|
+
return Object.keys(adapterPayload || {}).length !== 0;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
217
220
|
|
|
218
221
|
/**
|
|
219
222
|
This is a helper method that validates a JSON API top-level document
|
|
@@ -224,7 +227,7 @@ function assertIdentifierHasId(identifier) {
|
|
|
224
227
|
@internal
|
|
225
228
|
*/
|
|
226
229
|
function validateDocumentStructure(doc) {
|
|
227
|
-
if (
|
|
230
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
228
231
|
let errors = [];
|
|
229
232
|
if (!doc || typeof doc !== 'object') {
|
|
230
233
|
errors.push('Top level of a JSON API document must be an object');
|
|
@@ -275,29 +278,474 @@ function normalizeResponseHelper(serializer, store, modelClass, payload, id, req
|
|
|
275
278
|
validateDocumentStructure(normalizedResponse);
|
|
276
279
|
return normalizedResponse;
|
|
277
280
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
@module @ember-data/store
|
|
284
|
+
*/
|
|
285
|
+
/**
|
|
286
|
+
Snapshot is not directly instantiable.
|
|
287
|
+
Instances are provided to a consuming application's
|
|
288
|
+
adapters and serializers for certain requests.
|
|
289
|
+
|
|
290
|
+
Snapshots are only available when using `@ember-data/legacy-compat`
|
|
291
|
+
for legacy compatibility with adapters and serializers.
|
|
292
|
+
|
|
293
|
+
@class Snapshot
|
|
294
|
+
@public
|
|
295
|
+
*/
|
|
296
|
+
class Snapshot {
|
|
297
|
+
/**
|
|
298
|
+
* @method constructor
|
|
299
|
+
* @constructor
|
|
300
|
+
* @private
|
|
301
|
+
* @param options
|
|
302
|
+
* @param identifier
|
|
303
|
+
* @param _store
|
|
304
|
+
*/
|
|
305
|
+
constructor(options, identifier, store) {
|
|
306
|
+
this._store = store;
|
|
307
|
+
this.__attributes = null;
|
|
308
|
+
this._belongsToRelationships = Object.create(null);
|
|
309
|
+
this._belongsToIds = Object.create(null);
|
|
310
|
+
this._hasManyRelationships = Object.create(null);
|
|
311
|
+
this._hasManyIds = Object.create(null);
|
|
312
|
+
const hasRecord = !!store._instanceCache.peek({
|
|
313
|
+
identifier,
|
|
314
|
+
bucket: 'record'
|
|
315
|
+
});
|
|
316
|
+
this.modelName = identifier.type;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
The unique RecordIdentifier associated with this Snapshot.
|
|
320
|
+
@property identifier
|
|
321
|
+
@public
|
|
322
|
+
@type {StableRecordIdentifier}
|
|
323
|
+
*/
|
|
324
|
+
this.identifier = identifier;
|
|
325
|
+
|
|
326
|
+
/*
|
|
327
|
+
If the we do not yet have a record, then we are
|
|
328
|
+
likely a snapshot being provided to a find request, so we
|
|
329
|
+
populate __attributes lazily. Else, to preserve the "moment
|
|
330
|
+
in time" in which a snapshot is created, we greedily grab
|
|
331
|
+
the values.
|
|
332
|
+
*/
|
|
333
|
+
if (hasRecord) {
|
|
334
|
+
this._attributes;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
The id of the snapshot's underlying record
|
|
339
|
+
Example
|
|
340
|
+
```javascript
|
|
341
|
+
// store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
|
|
342
|
+
postSnapshot.id; // => '1'
|
|
343
|
+
```
|
|
344
|
+
@property id
|
|
345
|
+
@type {String}
|
|
346
|
+
@public
|
|
347
|
+
*/
|
|
348
|
+
this.id = identifier.id;
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
A hash of adapter options
|
|
352
|
+
@property adapterOptions
|
|
353
|
+
@type {Object}
|
|
354
|
+
@public
|
|
355
|
+
*/
|
|
356
|
+
this.adapterOptions = options.adapterOptions;
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
If `include` was passed to the options hash for the request, the value
|
|
360
|
+
would be available here.
|
|
361
|
+
@property include
|
|
362
|
+
@type {String|Array}
|
|
363
|
+
@public
|
|
364
|
+
*/
|
|
365
|
+
this.include = options.include;
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
The name of the type of the underlying record for this snapshot, as a string.
|
|
369
|
+
@property modelName
|
|
370
|
+
@type {String}
|
|
371
|
+
@public
|
|
372
|
+
*/
|
|
373
|
+
this.modelName = identifier.type;
|
|
374
|
+
if (hasRecord) {
|
|
375
|
+
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._store._instanceCache.getResourceCache(identifier) : this._store.cache;
|
|
376
|
+
this._changedAttributes = cache.changedAttrs(identifier);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
The underlying record for this snapshot. Can be used to access methods and
|
|
382
|
+
properties defined on the record.
|
|
383
|
+
Example
|
|
384
|
+
```javascript
|
|
385
|
+
let json = snapshot.record.toJSON();
|
|
386
|
+
```
|
|
387
|
+
@property record
|
|
388
|
+
@type {Model}
|
|
389
|
+
@public
|
|
390
|
+
*/
|
|
391
|
+
get record() {
|
|
392
|
+
return this._store._instanceCache.getRecord(this.identifier);
|
|
393
|
+
}
|
|
394
|
+
get _attributes() {
|
|
395
|
+
if (this.__attributes !== null) {
|
|
396
|
+
return this.__attributes;
|
|
397
|
+
}
|
|
398
|
+
const attributes = this.__attributes = Object.create(null);
|
|
399
|
+
const {
|
|
400
|
+
identifier
|
|
401
|
+
} = this;
|
|
402
|
+
const attrs = Object.keys(this._store.getSchemaDefinitionService().attributesDefinitionFor(identifier));
|
|
403
|
+
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._store._instanceCache.getResourceCache(identifier) : this._store.cache;
|
|
404
|
+
attrs.forEach(keyName => {
|
|
405
|
+
attributes[keyName] = cache.getAttr(identifier, keyName);
|
|
406
|
+
});
|
|
407
|
+
return attributes;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
The type of the underlying record for this snapshot, as a Model.
|
|
412
|
+
@property type
|
|
413
|
+
@public
|
|
414
|
+
@deprecated
|
|
415
|
+
@type {Model}
|
|
416
|
+
*/
|
|
417
|
+
|
|
418
|
+
get isNew() {
|
|
419
|
+
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? this._store._instanceCache.peek({
|
|
420
|
+
identifier: this.identifier,
|
|
421
|
+
bucket: 'resourceCache'
|
|
422
|
+
}) : this._store.cache;
|
|
423
|
+
return cache?.isNew(this.identifier) || false;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
Returns the value of an attribute.
|
|
428
|
+
Example
|
|
429
|
+
```javascript
|
|
430
|
+
// store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
|
|
431
|
+
postSnapshot.attr('author'); // => 'Tomster'
|
|
432
|
+
postSnapshot.attr('title'); // => 'Ember.js rocks'
|
|
433
|
+
```
|
|
434
|
+
Note: Values are loaded eagerly and cached when the snapshot is created.
|
|
435
|
+
@method attr
|
|
436
|
+
@param {String} keyName
|
|
437
|
+
@return {Object} The attribute value or undefined
|
|
438
|
+
@public
|
|
439
|
+
*/
|
|
440
|
+
attr(keyName) {
|
|
441
|
+
if (keyName in this._attributes) {
|
|
442
|
+
return this._attributes[keyName];
|
|
443
|
+
}
|
|
444
|
+
assert(`Model '${this.identifier.lid}' has no attribute named '${keyName}' defined.`, false);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
Returns all attributes and their corresponding values.
|
|
449
|
+
Example
|
|
450
|
+
```javascript
|
|
451
|
+
// store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
|
|
452
|
+
postSnapshot.attributes(); // => { author: 'Tomster', title: 'Ember.js rocks' }
|
|
453
|
+
```
|
|
454
|
+
@method attributes
|
|
455
|
+
@return {Object} All attributes of the current snapshot
|
|
456
|
+
@public
|
|
457
|
+
*/
|
|
458
|
+
attributes() {
|
|
459
|
+
return {
|
|
460
|
+
...this._attributes
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
Returns all changed attributes and their old and new values.
|
|
466
|
+
Example
|
|
467
|
+
```javascript
|
|
468
|
+
// store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
|
|
469
|
+
postModel.set('title', 'Ember.js rocks!');
|
|
470
|
+
postSnapshot.changedAttributes(); // => { title: ['Ember.js rocks', 'Ember.js rocks!'] }
|
|
471
|
+
```
|
|
472
|
+
@method changedAttributes
|
|
473
|
+
@return {Object} All changed attributes of the current snapshot
|
|
474
|
+
@public
|
|
475
|
+
*/
|
|
476
|
+
changedAttributes() {
|
|
477
|
+
let changedAttributes = Object.create(null);
|
|
478
|
+
if (!this._changedAttributes) {
|
|
479
|
+
return changedAttributes;
|
|
480
|
+
}
|
|
481
|
+
let changedAttributeKeys = Object.keys(this._changedAttributes);
|
|
482
|
+
for (let i = 0, length = changedAttributeKeys.length; i < length; i++) {
|
|
483
|
+
let key = changedAttributeKeys[i];
|
|
484
|
+
changedAttributes[key] = this._changedAttributes[key].slice();
|
|
485
|
+
}
|
|
486
|
+
return changedAttributes;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
Returns the current value of a belongsTo relationship.
|
|
491
|
+
`belongsTo` takes an optional hash of options as a second parameter,
|
|
492
|
+
currently supported options are:
|
|
493
|
+
- `id`: set to `true` if you only want the ID of the related record to be
|
|
494
|
+
returned.
|
|
495
|
+
Example
|
|
496
|
+
```javascript
|
|
497
|
+
// store.push('post', { id: 1, title: 'Hello World' });
|
|
498
|
+
// store.createRecord('comment', { body: 'Lorem ipsum', post: post });
|
|
499
|
+
commentSnapshot.belongsTo('post'); // => Snapshot
|
|
500
|
+
commentSnapshot.belongsTo('post', { id: true }); // => '1'
|
|
501
|
+
// store.push('comment', { id: 1, body: 'Lorem ipsum' });
|
|
502
|
+
commentSnapshot.belongsTo('post'); // => undefined
|
|
503
|
+
```
|
|
504
|
+
Calling `belongsTo` will return a new Snapshot as long as there's any known
|
|
505
|
+
data for the relationship available, such as an ID. If the relationship is
|
|
506
|
+
known but unset, `belongsTo` will return `null`. If the contents of the
|
|
507
|
+
relationship is unknown `belongsTo` will return `undefined`.
|
|
508
|
+
Note: Relationships are loaded lazily and cached upon first access.
|
|
509
|
+
@method belongsTo
|
|
510
|
+
@param {String} keyName
|
|
511
|
+
@param {Object} [options]
|
|
512
|
+
@public
|
|
513
|
+
@return {(Snapshot|String|null|undefined)} A snapshot or ID of a known
|
|
514
|
+
relationship or null if the relationship is known but unset. undefined
|
|
515
|
+
will be returned if the contents of the relationship is unknown.
|
|
516
|
+
*/
|
|
517
|
+
belongsTo(keyName, options) {
|
|
518
|
+
let returnModeIsId = !!(options && options.id);
|
|
519
|
+
let result;
|
|
520
|
+
let store = this._store;
|
|
521
|
+
if (returnModeIsId === true && keyName in this._belongsToIds) {
|
|
522
|
+
return this._belongsToIds[keyName];
|
|
523
|
+
}
|
|
524
|
+
if (returnModeIsId === false && keyName in this._belongsToRelationships) {
|
|
525
|
+
return this._belongsToRelationships[keyName];
|
|
526
|
+
}
|
|
527
|
+
let relationshipMeta = store.getSchemaDefinitionService().relationshipsDefinitionFor({
|
|
528
|
+
type: this.modelName
|
|
529
|
+
})[keyName];
|
|
530
|
+
assert(`Model '${this.identifier.lid}' has no belongsTo relationship named '${keyName}' defined.`, relationshipMeta && relationshipMeta.kind === 'belongsTo');
|
|
531
|
+
|
|
532
|
+
// TODO @runspired it seems this code branch would not work with CUSTOM_MODEL_CLASSes
|
|
533
|
+
// this check is not a regression in behavior because relationships don't currently
|
|
534
|
+
// function without access to intimate API contracts between RecordData and Model.
|
|
535
|
+
// This is a requirement we should fix as soon as the relationship layer does not require
|
|
536
|
+
// this intimate API usage.
|
|
537
|
+
if (macroCondition(!getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
|
|
538
|
+
assert(`snapshot.belongsTo only supported when using the package @ember-data/json-api`);
|
|
539
|
+
}
|
|
540
|
+
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
541
|
+
const {
|
|
542
|
+
identifier
|
|
543
|
+
} = this;
|
|
544
|
+
const relationship = graphFor(this._store).get(identifier, keyName);
|
|
545
|
+
assert(`You looked up the ${keyName} belongsTo relationship for { type: ${identifier.type}, id: ${identifier.id || ''}, lid: ${identifier.lid} but no such relationship was found.`, relationship);
|
|
546
|
+
assert(`You looked up the ${keyName} belongsTo relationship for { type: ${identifier.type}, id: ${identifier.id || ''}, lid: ${identifier.lid} but that relationship is a hasMany.`, relationship.definition.kind === 'belongsTo');
|
|
547
|
+
let value = relationship.getData();
|
|
548
|
+
let data = value && value.data;
|
|
549
|
+
let inverseIdentifier = data ? store.identifierCache.getOrCreateRecordIdentifier(data) : null;
|
|
550
|
+
if (value && value.data !== undefined) {
|
|
551
|
+
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? inverseIdentifier && store._instanceCache.getResourceCache(inverseIdentifier) : store.cache;
|
|
552
|
+
if (inverseIdentifier && !cache.isDeleted(inverseIdentifier)) {
|
|
553
|
+
if (returnModeIsId) {
|
|
554
|
+
result = inverseIdentifier.id;
|
|
555
|
+
} else {
|
|
556
|
+
result = store._fetchManager.createSnapshot(inverseIdentifier);
|
|
557
|
+
}
|
|
558
|
+
} else {
|
|
559
|
+
result = null;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
if (returnModeIsId) {
|
|
563
|
+
this._belongsToIds[keyName] = result;
|
|
564
|
+
} else {
|
|
565
|
+
this._belongsToRelationships[keyName] = result;
|
|
566
|
+
}
|
|
567
|
+
return result;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
Returns the current value of a hasMany relationship.
|
|
572
|
+
`hasMany` takes an optional hash of options as a second parameter,
|
|
573
|
+
currently supported options are:
|
|
574
|
+
- `ids`: set to `true` if you only want the IDs of the related records to be
|
|
575
|
+
returned.
|
|
576
|
+
Example
|
|
577
|
+
```javascript
|
|
578
|
+
// store.push('post', { id: 1, title: 'Hello World', comments: [2, 3] });
|
|
579
|
+
postSnapshot.hasMany('comments'); // => [Snapshot, Snapshot]
|
|
580
|
+
postSnapshot.hasMany('comments', { ids: true }); // => ['2', '3']
|
|
581
|
+
// store.push('post', { id: 1, title: 'Hello World' });
|
|
582
|
+
postSnapshot.hasMany('comments'); // => undefined
|
|
583
|
+
```
|
|
584
|
+
Note: Relationships are loaded lazily and cached upon first access.
|
|
585
|
+
@method hasMany
|
|
586
|
+
@param {String} keyName
|
|
587
|
+
@param {Object} [options]
|
|
588
|
+
@public
|
|
589
|
+
@return {(Array|undefined)} An array of snapshots or IDs of a known
|
|
590
|
+
relationship or an empty array if the relationship is known but unset.
|
|
591
|
+
undefined will be returned if the contents of the relationship is unknown.
|
|
592
|
+
*/
|
|
593
|
+
hasMany(keyName, options) {
|
|
594
|
+
let returnModeIsIds = !!(options && options.ids);
|
|
595
|
+
let results;
|
|
596
|
+
let cachedIds = this._hasManyIds[keyName];
|
|
597
|
+
let cachedSnapshots = this._hasManyRelationships[keyName];
|
|
598
|
+
if (returnModeIsIds === true && keyName in this._hasManyIds) {
|
|
599
|
+
return cachedIds;
|
|
600
|
+
}
|
|
601
|
+
if (returnModeIsIds === false && keyName in this._hasManyRelationships) {
|
|
602
|
+
return cachedSnapshots;
|
|
603
|
+
}
|
|
604
|
+
let store = this._store;
|
|
605
|
+
let relationshipMeta = store.getSchemaDefinitionService().relationshipsDefinitionFor({
|
|
606
|
+
type: this.modelName
|
|
607
|
+
})[keyName];
|
|
608
|
+
assert(`Model '${this.identifier.lid}' has no hasMany relationship named '${keyName}' defined.`, relationshipMeta && relationshipMeta.kind === 'hasMany');
|
|
609
|
+
|
|
610
|
+
// TODO @runspired it seems this code branch would not work with CUSTOM_MODEL_CLASSes
|
|
611
|
+
// this check is not a regression in behavior because relationships don't currently
|
|
612
|
+
// function without access to intimate API contracts between RecordData and Model.
|
|
613
|
+
// This is a requirement we should fix as soon as the relationship layer does not require
|
|
614
|
+
// this intimate API usage.
|
|
615
|
+
if (macroCondition(!getOwnConfig().packages.HAS_JSON_API_PACKAGE)) {
|
|
616
|
+
assert(`snapshot.hasMany only supported when using the package @ember-data/json-api`);
|
|
617
|
+
}
|
|
618
|
+
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
619
|
+
const {
|
|
620
|
+
identifier
|
|
621
|
+
} = this;
|
|
622
|
+
const relationship = graphFor(this._store).get(identifier, keyName);
|
|
623
|
+
assert(`You looked up the ${keyName} hasMany relationship for { type: ${identifier.type}, id: ${identifier.id || ''}, lid: ${identifier.lid} but no such relationship was found.`, relationship);
|
|
624
|
+
assert(`You looked up the ${keyName} hasMany relationship for { type: ${identifier.type}, id: ${identifier.id || ''}, lid: ${identifier.lid} but that relationship is a belongsTo.`, relationship.definition.kind === 'hasMany');
|
|
625
|
+
let value = relationship.getData();
|
|
626
|
+
if (value.data) {
|
|
627
|
+
results = [];
|
|
628
|
+
value.data.forEach(member => {
|
|
629
|
+
let inverseIdentifier = store.identifierCache.getOrCreateRecordIdentifier(member);
|
|
630
|
+
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? store._instanceCache.getResourceCache(inverseIdentifier) : store.cache;
|
|
631
|
+
if (!cache.isDeleted(inverseIdentifier)) {
|
|
632
|
+
if (returnModeIsIds) {
|
|
633
|
+
results.push(inverseIdentifier.id);
|
|
634
|
+
} else {
|
|
635
|
+
results.push(store._fetchManager.createSnapshot(inverseIdentifier));
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// we assign even if `undefined` so that we don't reprocess the relationship
|
|
642
|
+
// on next access. This works with the `keyName in` checks above.
|
|
643
|
+
if (returnModeIsIds) {
|
|
644
|
+
this._hasManyIds[keyName] = results;
|
|
645
|
+
} else {
|
|
646
|
+
this._hasManyRelationships[keyName] = results;
|
|
647
|
+
}
|
|
648
|
+
return results;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
Iterates through all the attributes of the model, calling the passed
|
|
653
|
+
function on each attribute.
|
|
654
|
+
Example
|
|
655
|
+
```javascript
|
|
656
|
+
snapshot.eachAttribute(function(name, meta) {
|
|
657
|
+
// ...
|
|
658
|
+
});
|
|
659
|
+
```
|
|
660
|
+
@method eachAttribute
|
|
661
|
+
@param {Function} callback the callback to execute
|
|
662
|
+
@param {Object} [binding] the value to which the callback's `this` should be bound
|
|
663
|
+
@public
|
|
664
|
+
*/
|
|
665
|
+
eachAttribute(callback, binding) {
|
|
666
|
+
let attrDefs = this._store.getSchemaDefinitionService().attributesDefinitionFor(this.identifier);
|
|
667
|
+
Object.keys(attrDefs).forEach(key => {
|
|
668
|
+
callback.call(binding, key, attrDefs[key]);
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
Iterates through all the relationships of the model, calling the passed
|
|
674
|
+
function on each relationship.
|
|
675
|
+
Example
|
|
676
|
+
```javascript
|
|
677
|
+
snapshot.eachRelationship(function(name, relationship) {
|
|
678
|
+
// ...
|
|
679
|
+
});
|
|
680
|
+
```
|
|
681
|
+
@method eachRelationship
|
|
682
|
+
@param {Function} callback the callback to execute
|
|
683
|
+
@param {Object} [binding] the value to which the callback's `this` should be bound
|
|
684
|
+
@public
|
|
685
|
+
*/
|
|
686
|
+
eachRelationship(callback, binding) {
|
|
687
|
+
let relationshipDefs = this._store.getSchemaDefinitionService().relationshipsDefinitionFor(this.identifier);
|
|
688
|
+
Object.keys(relationshipDefs).forEach(key => {
|
|
689
|
+
callback.call(binding, key, relationshipDefs[key]);
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
Serializes the snapshot using the serializer for the model.
|
|
695
|
+
Example
|
|
696
|
+
```app/adapters/application.js
|
|
697
|
+
import Adapter from '@ember-data/adapter';
|
|
698
|
+
export default Adapter.extend({
|
|
699
|
+
createRecord(store, type, snapshot) {
|
|
700
|
+
let data = snapshot.serialize({ includeId: true });
|
|
701
|
+
let url = `/${type.modelName}`;
|
|
702
|
+
return fetch(url, {
|
|
703
|
+
method: 'POST',
|
|
704
|
+
body: data,
|
|
705
|
+
}).then((response) => response.json())
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
```
|
|
709
|
+
@method serialize
|
|
710
|
+
@param {Object} options
|
|
711
|
+
@return {Object} an object whose values are primitive JSON values only
|
|
712
|
+
@public
|
|
713
|
+
*/
|
|
714
|
+
serialize(options) {
|
|
715
|
+
const serializer = this._store.serializerFor(this.modelName);
|
|
716
|
+
assert(`Cannot serialize record, no serializer found`, serializer);
|
|
717
|
+
return serializer.serialize(this, options);
|
|
283
718
|
}
|
|
284
719
|
}
|
|
720
|
+
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_SNAPSHOT_MODEL_CLASS_ACCESS)) {
|
|
721
|
+
Object.defineProperty(Snapshot.prototype, 'type', {
|
|
722
|
+
get() {
|
|
723
|
+
deprecate(`Using Snapshot.type to access the ModelClass for a record is deprecated. Use store.modelFor(<modelName>) instead.`, false, {
|
|
724
|
+
id: 'ember-data:deprecate-snapshot-model-class-access',
|
|
725
|
+
until: '5.0',
|
|
726
|
+
for: 'ember-data',
|
|
727
|
+
since: {
|
|
728
|
+
available: '4.5.0',
|
|
729
|
+
enabled: '4.5.0'
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
return this._store.modelFor(this.identifier.type);
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
}
|
|
285
736
|
const SaveOp = Symbol('SaveOp');
|
|
286
737
|
class FetchManager {
|
|
287
|
-
// saves which are pending in the runloop
|
|
288
|
-
|
|
289
738
|
// fetches pending in the runloop, waiting to be coalesced
|
|
290
739
|
|
|
291
740
|
constructor(store) {
|
|
292
741
|
this._store = store;
|
|
293
742
|
// used to keep track of all the find requests that need to be coalesced
|
|
294
743
|
this._pendingFetch = new Map();
|
|
295
|
-
this._pendingSave = [];
|
|
296
744
|
this.requestCache = store.getRequestStateService();
|
|
297
745
|
this.isDestroyed = false;
|
|
298
746
|
}
|
|
299
|
-
|
|
300
|
-
return
|
|
747
|
+
createSnapshot(identifier, options = {}) {
|
|
748
|
+
return new Snapshot(options, identifier, this._store);
|
|
301
749
|
}
|
|
302
750
|
|
|
303
751
|
/**
|
|
@@ -307,7 +755,7 @@ class FetchManager {
|
|
|
307
755
|
@internal
|
|
308
756
|
*/
|
|
309
757
|
scheduleSave(identifier, options) {
|
|
310
|
-
let resolver =
|
|
758
|
+
let resolver = createDeferred();
|
|
311
759
|
let query = {
|
|
312
760
|
op: 'saveRecord',
|
|
313
761
|
recordIdentifier: identifier,
|
|
@@ -316,7 +764,7 @@ class FetchManager {
|
|
|
316
764
|
let queryRequest = {
|
|
317
765
|
data: [query]
|
|
318
766
|
};
|
|
319
|
-
const snapshot = this.
|
|
767
|
+
const snapshot = this.createSnapshot(identifier, options);
|
|
320
768
|
const pendingSaveItem = {
|
|
321
769
|
snapshot: snapshot,
|
|
322
770
|
resolver: resolver,
|
|
@@ -324,30 +772,11 @@ class FetchManager {
|
|
|
324
772
|
options,
|
|
325
773
|
queryRequest
|
|
326
774
|
};
|
|
327
|
-
this.
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
this.requestCache.enqueue(resolver.promise, pendingSaveItem.queryRequest);
|
|
331
|
-
return resolver.promise;
|
|
775
|
+
const monitored = this.requestCache.enqueue(resolver.promise, pendingSaveItem.queryRequest);
|
|
776
|
+
_flushPendingSave(this._store, pendingSaveItem);
|
|
777
|
+
return monitored;
|
|
332
778
|
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
This method is called at the end of the run loop, and
|
|
336
|
-
flushes any records passed into `scheduleSave`
|
|
337
|
-
@internal
|
|
338
|
-
*/
|
|
339
|
-
_flushPendingSaves() {
|
|
340
|
-
const store = this._store;
|
|
341
|
-
let pending = this._pendingSave.slice();
|
|
342
|
-
this._pendingSave = [];
|
|
343
|
-
for (let i = 0, j = pending.length; i < j; i++) {
|
|
344
|
-
let pendingItem = pending[i];
|
|
345
|
-
_flushPendingSave(store, pendingItem);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
scheduleFetch(identifier, options) {
|
|
349
|
-
// TODO Probably the store should pass in the query object
|
|
350
|
-
let shouldTrace = isDevelopingApp() && this._store.generateStackTracesForTrackedRequests;
|
|
779
|
+
scheduleFetch(identifier, options, request) {
|
|
351
780
|
let query = {
|
|
352
781
|
op: 'findRecord',
|
|
353
782
|
recordIdentifier: identifier,
|
|
@@ -360,36 +789,20 @@ class FetchManager {
|
|
|
360
789
|
if (pendingFetch) {
|
|
361
790
|
return pendingFetch;
|
|
362
791
|
}
|
|
363
|
-
let id = identifier.id;
|
|
364
792
|
let modelName = identifier.type;
|
|
365
|
-
|
|
366
|
-
|
|
793
|
+
const resolver = createDeferred();
|
|
794
|
+
const pendingFetchItem = {
|
|
367
795
|
identifier,
|
|
368
796
|
resolver,
|
|
369
797
|
options,
|
|
370
798
|
queryRequest
|
|
371
799
|
};
|
|
372
|
-
if (isDevelopingApp()) {
|
|
373
|
-
if (shouldTrace) {
|
|
374
|
-
let trace;
|
|
375
|
-
try {
|
|
376
|
-
throw new Error(`Trace Origin for scheduled fetch for ${modelName}:${id}.`);
|
|
377
|
-
} catch (e) {
|
|
378
|
-
trace = e;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// enable folks to discover the origin of this findRecord call when
|
|
382
|
-
// debugging. Ideally we would have a tracked queue for requests with
|
|
383
|
-
// labels or local IDs that could be used to merge this trace with
|
|
384
|
-
// the trace made available when we detect an async leak
|
|
385
|
-
pendingFetchItem.trace = trace;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
800
|
let resolverPromise = resolver.promise;
|
|
389
801
|
const store = this._store;
|
|
390
|
-
const
|
|
802
|
+
const isInitialLoad = !store._instanceCache.recordIsLoaded(identifier); // we don't use isLoading directly because we are the request
|
|
391
803
|
|
|
392
|
-
const
|
|
804
|
+
const monitored = this.requestCache.enqueue(resolverPromise, pendingFetchItem.queryRequest);
|
|
805
|
+
let promise = monitored.then(payload => {
|
|
393
806
|
// ensure that regardless of id returned we assign to the correct record
|
|
394
807
|
if (payload.data && !Array.isArray(payload.data)) {
|
|
395
808
|
payload.data.lid = identifier.lid;
|
|
@@ -397,17 +810,18 @@ class FetchManager {
|
|
|
397
810
|
|
|
398
811
|
// additional data received in the payload
|
|
399
812
|
// may result in the merging of identifiers (and thus records)
|
|
400
|
-
let potentiallyNewIm = store._push(payload);
|
|
813
|
+
let potentiallyNewIm = store._push(payload, options.reload);
|
|
401
814
|
if (potentiallyNewIm && !Array.isArray(potentiallyNewIm)) {
|
|
402
815
|
return potentiallyNewIm;
|
|
403
816
|
}
|
|
404
817
|
return identifier;
|
|
405
818
|
}, error => {
|
|
819
|
+
assert(`Async Leak Detected: Expected the store to not be destroyed`, !store.isDestroyed);
|
|
406
820
|
const cache = macroCondition(getOwnConfig().deprecations.DEPRECATE_V1_RECORD_DATA) ? store._instanceCache.peek({
|
|
407
821
|
identifier,
|
|
408
822
|
bucket: 'resourceCache'
|
|
409
823
|
}) : store.cache;
|
|
410
|
-
if (!cache || cache.isEmpty(identifier) ||
|
|
824
|
+
if (!cache || cache.isEmpty(identifier) || isInitialLoad) {
|
|
411
825
|
let isReleasable = true;
|
|
412
826
|
if (macroCondition(getOwnConfig().packages.HAS_GRAPH_PACKAGE)) {
|
|
413
827
|
if (!cache) {
|
|
@@ -420,22 +834,32 @@ class FetchManager {
|
|
|
420
834
|
}
|
|
421
835
|
}
|
|
422
836
|
if (cache || isReleasable) {
|
|
837
|
+
store._enableAsyncFlush = true;
|
|
423
838
|
store._instanceCache.unloadRecord(identifier);
|
|
839
|
+
store._enableAsyncFlush = null;
|
|
424
840
|
}
|
|
425
841
|
}
|
|
426
842
|
throw error;
|
|
427
843
|
});
|
|
428
844
|
if (this._pendingFetch.size === 0) {
|
|
429
|
-
|
|
430
|
-
|
|
845
|
+
void new Promise(resolve => setTimeout(resolve, 0)).then(() => {
|
|
846
|
+
this.flushAllPendingFetches();
|
|
847
|
+
});
|
|
431
848
|
}
|
|
432
849
|
let fetches = this._pendingFetch;
|
|
433
850
|
if (!fetches.has(modelName)) {
|
|
434
851
|
fetches.set(modelName, []);
|
|
435
852
|
}
|
|
436
853
|
fetches.get(modelName).push(pendingFetchItem);
|
|
854
|
+
if (macroCondition(getOwnConfig().env.TESTING)) {
|
|
855
|
+
if (!request.disableTestWaiter) {
|
|
856
|
+
const {
|
|
857
|
+
waitForPromise
|
|
858
|
+
} = importSync('@ember/test-waiters');
|
|
859
|
+
promise = waitForPromise(promise);
|
|
860
|
+
}
|
|
861
|
+
}
|
|
437
862
|
pendingFetchItem.promise = promise;
|
|
438
|
-
this.requestCache.enqueue(resolverPromise, pendingFetchItem.queryRequest);
|
|
439
863
|
return promise;
|
|
440
864
|
}
|
|
441
865
|
getPendingFetch(identifier, options) {
|
|
@@ -457,19 +881,26 @@ class FetchManager {
|
|
|
457
881
|
this._pendingFetch.forEach((fetchItem, type) => _flushPendingFetchForType(store, fetchItem, type));
|
|
458
882
|
this._pendingFetch.clear();
|
|
459
883
|
}
|
|
460
|
-
fetchDataIfNeededForIdentifier(identifier, options = {}) {
|
|
884
|
+
fetchDataIfNeededForIdentifier(identifier, options = {}, request) {
|
|
461
885
|
// pre-loading will change the isEmpty value
|
|
462
886
|
const isEmpty = _isEmpty(this._store._instanceCache, identifier);
|
|
463
887
|
const isLoading = _isLoading(this._store._instanceCache, identifier);
|
|
464
888
|
let promise;
|
|
465
889
|
if (isEmpty) {
|
|
466
890
|
assertIdentifierHasId(identifier);
|
|
467
|
-
|
|
891
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
892
|
+
promise = this.scheduleFetch(identifier, Object.assign({}, options, {
|
|
893
|
+
reload: true
|
|
894
|
+
}), request);
|
|
895
|
+
} else {
|
|
896
|
+
options.reload = true;
|
|
897
|
+
promise = this.scheduleFetch(identifier, options, request);
|
|
898
|
+
}
|
|
468
899
|
} else if (isLoading) {
|
|
469
900
|
promise = this.getPendingFetch(identifier, options);
|
|
470
901
|
assert(`Expected to find a pending request for a record in the loading state, but found none`, promise);
|
|
471
902
|
} else {
|
|
472
|
-
promise = resolve(identifier);
|
|
903
|
+
promise = Promise.resolve(identifier);
|
|
473
904
|
}
|
|
474
905
|
return promise;
|
|
475
906
|
}
|
|
@@ -504,18 +935,18 @@ function isSameRequest(options = {}, existingOptions = {}) {
|
|
|
504
935
|
}
|
|
505
936
|
function _findMany(store, adapter, modelName, snapshots) {
|
|
506
937
|
let modelClass = store.modelFor(modelName); // `adapter.findMany` gets the modelClass still
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
}
|
|
516
|
-
promise = guardDestroyedStore(promise, store
|
|
938
|
+
let promise = Promise.resolve().then(() => {
|
|
939
|
+
const ids = snapshots.map(s => s.id);
|
|
940
|
+
assert(`Cannot fetch a record without an id`, ids.every(v => v !== null));
|
|
941
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
942
|
+
assert(`Expected this adapter to implement findMany for coalescing`, adapter.findMany);
|
|
943
|
+
let ret = adapter.findMany(store, modelClass, ids, snapshots);
|
|
944
|
+
assert('adapter.findMany returned undefined, this was very likely a mistake', ret !== undefined);
|
|
945
|
+
return ret;
|
|
946
|
+
});
|
|
947
|
+
promise = guardDestroyedStore(promise, store);
|
|
517
948
|
return promise.then(adapterPayload => {
|
|
518
|
-
assert(`You made a 'findMany' request for '${modelName}' records with ids '[${
|
|
949
|
+
assert(`You made a 'findMany' request for '${modelName}' records with ids '[${snapshots.map(s => s.id).join(',')}]', but the adapter's response did not have any data`, !!payloadIsNotBlank(adapterPayload));
|
|
519
950
|
let serializer = store.serializerFor(modelName);
|
|
520
951
|
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findMany');
|
|
521
952
|
return payload;
|
|
@@ -575,7 +1006,7 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
575
1006
|
store._push({
|
|
576
1007
|
data: null,
|
|
577
1008
|
included
|
|
578
|
-
});
|
|
1009
|
+
}, true);
|
|
579
1010
|
}
|
|
580
1011
|
if (snapshotsById.size === 0) {
|
|
581
1012
|
return;
|
|
@@ -591,20 +1022,19 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
591
1022
|
});
|
|
592
1023
|
rejectFetchedItems(fetchMap, rejected);
|
|
593
1024
|
}
|
|
594
|
-
function _fetchRecord(store, fetchItem) {
|
|
1025
|
+
function _fetchRecord(store, adapter, fetchItem) {
|
|
595
1026
|
let identifier = fetchItem.identifier;
|
|
596
1027
|
let modelName = identifier.type;
|
|
597
|
-
let adapter = store.adapterFor(modelName);
|
|
598
1028
|
assert(`You tried to find a record but you have no adapter (for ${modelName})`, adapter);
|
|
599
1029
|
assert(`You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`, typeof adapter.findRecord === 'function');
|
|
600
|
-
let snapshot = store.
|
|
1030
|
+
let snapshot = store._fetchManager.createSnapshot(identifier, fetchItem.options);
|
|
601
1031
|
let klass = store.modelFor(identifier.type);
|
|
602
1032
|
let id = identifier.id;
|
|
603
|
-
let
|
|
604
|
-
let promise = guardDestroyedStore(resolve().then(() => {
|
|
1033
|
+
let promise = Promise.resolve().then(() => {
|
|
605
1034
|
return adapter.findRecord(store, klass, identifier.id, snapshot);
|
|
606
|
-
})
|
|
1035
|
+
});
|
|
607
1036
|
promise = promise.then(adapterPayload => {
|
|
1037
|
+
assert(`Async Leak Detected: Expected the store to not be destroyed`, _objectIsAlive(store));
|
|
608
1038
|
assert(`You made a 'findRecord' request for a '${modelName}' with id '${id}', but the adapter's response did not have any data`, !!payloadIsNotBlank(adapterPayload));
|
|
609
1039
|
let serializer = store.serializerFor(modelName);
|
|
610
1040
|
let payload = normalizeResponseHelper(serializer, store, klass, adapterPayload, id, 'findRecord');
|
|
@@ -625,7 +1055,7 @@ function _processCoalescedGroup(store, fetchMap, group, adapter, modelName) {
|
|
|
625
1055
|
rejectFetchedItems(fetchMap, group, error);
|
|
626
1056
|
});
|
|
627
1057
|
} else if (group.length === 1) {
|
|
628
|
-
_fetchRecord(store, fetchMap.get(group[0]));
|
|
1058
|
+
_fetchRecord(store, adapter, fetchMap.get(group[0]));
|
|
629
1059
|
} else {
|
|
630
1060
|
assert("You cannot return an empty array from adapter's method groupRecordsForFindMany", false);
|
|
631
1061
|
}
|
|
@@ -639,7 +1069,7 @@ function _flushPendingFetchForType(store, pendingFetchItems, modelName) {
|
|
|
639
1069
|
let fetchMap = new Map();
|
|
640
1070
|
for (let i = 0; i < totalItems; i++) {
|
|
641
1071
|
let fetchItem = pendingFetchItems[i];
|
|
642
|
-
snapshots[i] = store.
|
|
1072
|
+
snapshots[i] = store._fetchManager.createSnapshot(fetchItem.identifier, fetchItem.options);
|
|
643
1073
|
fetchMap.set(snapshots[i], fetchItem);
|
|
644
1074
|
}
|
|
645
1075
|
let groups;
|
|
@@ -653,7 +1083,7 @@ function _flushPendingFetchForType(store, pendingFetchItems, modelName) {
|
|
|
653
1083
|
}
|
|
654
1084
|
} else {
|
|
655
1085
|
for (let i = 0; i < totalItems; i++) {
|
|
656
|
-
_fetchRecord(store, pendingFetchItems[i]);
|
|
1086
|
+
void _fetchRecord(store, adapter, pendingFetchItems[i]);
|
|
657
1087
|
}
|
|
658
1088
|
}
|
|
659
1089
|
}
|
|
@@ -671,14 +1101,9 @@ function _flushPendingSave(store, pending) {
|
|
|
671
1101
|
const record = store._instanceCache.getRecord(identifier);
|
|
672
1102
|
assert(`You tried to update a record but you have no adapter (for ${modelName})`, adapter);
|
|
673
1103
|
assert(`You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`, typeof adapter[operation] === 'function');
|
|
674
|
-
let promise = resolve().then(() => adapter[operation](store, modelClass, snapshot));
|
|
1104
|
+
let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot));
|
|
675
1105
|
let serializer = store.serializerFor(modelName);
|
|
676
1106
|
assert(`Your adapter's '${operation}' method must return a value, but it returned 'undefined'`, promise !== undefined);
|
|
677
|
-
|
|
678
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
679
|
-
promise = _guard(guardDestroyedStore(promise, store, isDevelopingApp() ? `DS: Extract and notify about ${operation} completion of ${identifier.lid}` : ''),
|
|
680
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
681
|
-
_bind(_objectIsAlive, record));
|
|
682
1107
|
promise = promise.then(adapterPayload => {
|
|
683
1108
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
684
1109
|
if (!_objectIsAlive(record)) {
|
|
@@ -700,4 +1125,4 @@ function _flushPendingSave(store, pending) {
|
|
|
700
1125
|
});
|
|
701
1126
|
resolver.resolve(promise);
|
|
702
1127
|
}
|
|
703
|
-
export { FetchManager as F, SnapshotRecordArray as S, SaveOp as a,
|
|
1128
|
+
export { FetchManager as F, SnapshotRecordArray as S, _objectIsAlive as _, SaveOp as a, Snapshot as b, _guard as c, _bind as d, assertIdentifierHasId as e, guardDestroyedStore as g, iterateData as i, normalizeResponseHelper as n, payloadIsNotBlank as p };
|