@ember-data/legacy-compat 5.4.0-alpha.9 → 5.4.0-alpha.91
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/README.md +8 -0
- package/addon-main.cjs +5 -0
- package/{addon/fetch-manager-0744e8e9.js → dist/-private-DVN28hvw.js} +251 -125
- package/dist/-private-DVN28hvw.js.map +1 -0
- package/dist/-private.js +1 -0
- package/dist/builders.js +323 -0
- package/dist/builders.js.map +1 -0
- package/dist/index.js +1017 -0
- package/dist/index.js.map +1 -0
- package/dist/utils.js +246 -0
- package/dist/utils.js.map +1 -0
- package/package.json +74 -38
- package/unstable-preview-types/-private.d.ts +17 -0
- package/unstable-preview-types/-private.d.ts.map +1 -0
- package/unstable-preview-types/builders/find-all.d.ts +41 -0
- package/unstable-preview-types/builders/find-all.d.ts.map +1 -0
- package/unstable-preview-types/builders/find-record.d.ts +62 -0
- package/unstable-preview-types/builders/find-record.d.ts.map +1 -0
- package/unstable-preview-types/builders/query.d.ts +72 -0
- package/unstable-preview-types/builders/query.d.ts.map +1 -0
- package/unstable-preview-types/builders/save-record.d.ts +40 -0
- package/unstable-preview-types/builders/save-record.d.ts.map +1 -0
- package/unstable-preview-types/builders/utils.d.ts +6 -0
- package/unstable-preview-types/builders/utils.d.ts.map +1 -0
- package/unstable-preview-types/builders.d.ts +18 -0
- package/unstable-preview-types/builders.d.ts.map +1 -0
- package/unstable-preview-types/index.d.ts +162 -0
- package/unstable-preview-types/index.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/fetch-manager.d.ts +49 -0
- package/unstable-preview-types/legacy-network-handler/fetch-manager.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/identifier-has-id.d.ts +5 -0
- package/unstable-preview-types/legacy-network-handler/identifier-has-id.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/legacy-data-fetch.d.ts +14 -0
- package/unstable-preview-types/legacy-network-handler/legacy-data-fetch.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/legacy-data-utils.d.ts +8 -0
- package/unstable-preview-types/legacy-network-handler/legacy-data-utils.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/legacy-network-handler.d.ts +5 -0
- package/unstable-preview-types/legacy-network-handler/legacy-network-handler.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/minimum-adapter-interface.d.ts +549 -0
- package/unstable-preview-types/legacy-network-handler/minimum-adapter-interface.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/minimum-serializer-interface.d.ts +235 -0
- package/unstable-preview-types/legacy-network-handler/minimum-serializer-interface.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/serializer-response.d.ts +9 -0
- package/unstable-preview-types/legacy-network-handler/serializer-response.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/snapshot-record-array.d.ts +96 -0
- package/unstable-preview-types/legacy-network-handler/snapshot-record-array.d.ts.map +1 -0
- package/unstable-preview-types/legacy-network-handler/snapshot.d.ts +248 -0
- package/unstable-preview-types/legacy-network-handler/snapshot.d.ts.map +1 -0
- package/unstable-preview-types/utils.d.ts +161 -0
- package/unstable-preview-types/utils.d.ts.map +1 -0
- package/addon/-private.js +0 -1
- package/addon/fetch-manager-0744e8e9.js.map +0 -1
- package/addon/index.js +0 -617
- package/addon/index.js.map +0 -1
- package/addon-main.js +0 -93
- /package/{addon → dist}/-private.js.map +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { SOURCE, coerceId } from '@ember-data/store/-private';
|
|
2
|
-
import {
|
|
3
|
-
import { macroCondition,
|
|
2
|
+
import { warn } from '@ember/debug';
|
|
3
|
+
import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
|
|
4
4
|
import { createDeferred } from '@ember-data/request';
|
|
5
|
+
import { getOrSetGlobal } from '@warp-drive/core-types/-private';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
@module @ember-data/legacy-compat
|
|
@@ -10,7 +11,7 @@ import { createDeferred } from '@ember-data/request';
|
|
|
10
11
|
/**
|
|
11
12
|
SnapshotRecordArray is not directly instantiable.
|
|
12
13
|
Instances are provided to consuming application's
|
|
13
|
-
adapters for certain requests.
|
|
14
|
+
adapters for certain `findAll` requests.
|
|
14
15
|
|
|
15
16
|
@class SnapshotRecordArray
|
|
16
17
|
@public
|
|
@@ -140,6 +141,7 @@ class SnapshotRecordArray {
|
|
|
140
141
|
if (this._snapshots !== null) {
|
|
141
142
|
return this._snapshots;
|
|
142
143
|
}
|
|
144
|
+
upgradeStore(this.__store);
|
|
143
145
|
const {
|
|
144
146
|
_fetchManager
|
|
145
147
|
} = this.__store;
|
|
@@ -148,13 +150,17 @@ class SnapshotRecordArray {
|
|
|
148
150
|
}
|
|
149
151
|
}
|
|
150
152
|
function assertIdentifierHasId(identifier) {
|
|
151
|
-
|
|
153
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
154
|
+
if (!test) {
|
|
155
|
+
throw new Error(`Attempted to schedule a fetch for a record without an id.`);
|
|
156
|
+
}
|
|
157
|
+
})(identifier && identifier.id !== null) : {};
|
|
152
158
|
}
|
|
153
159
|
function iterateData(data, fn) {
|
|
154
160
|
if (Array.isArray(data)) {
|
|
155
161
|
return data.map(fn);
|
|
156
162
|
} else {
|
|
157
|
-
return fn(data);
|
|
163
|
+
return fn(data, 0);
|
|
158
164
|
}
|
|
159
165
|
}
|
|
160
166
|
function payloadIsNotBlank(adapterPayload) {
|
|
@@ -174,8 +180,8 @@ function payloadIsNotBlank(adapterPayload) {
|
|
|
174
180
|
@internal
|
|
175
181
|
*/
|
|
176
182
|
function validateDocumentStructure(doc) {
|
|
177
|
-
if (macroCondition(
|
|
178
|
-
|
|
183
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
184
|
+
const errors = [];
|
|
179
185
|
if (!doc || typeof doc !== 'object') {
|
|
180
186
|
errors.push('Top level of a JSON API document must be an object');
|
|
181
187
|
} else {
|
|
@@ -217,11 +223,15 @@ function validateDocumentStructure(doc) {
|
|
|
217
223
|
}
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
|
-
|
|
226
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
227
|
+
if (!test) {
|
|
228
|
+
throw new Error(`Response must be normalized to a valid JSON API document:\n\t* ${errors.join('\n\t* ')}`);
|
|
229
|
+
}
|
|
230
|
+
})(errors.length === 0) : {};
|
|
221
231
|
}
|
|
222
232
|
}
|
|
223
233
|
function normalizeResponseHelper(serializer, store, modelClass, payload, id, requestType) {
|
|
224
|
-
|
|
234
|
+
const normalizedResponse = serializer ? serializer.normalizeResponse(store, modelClass, payload, id, requestType) : payload;
|
|
225
235
|
validateDocumentStructure(normalizedResponse);
|
|
226
236
|
return normalizedResponse;
|
|
227
237
|
}
|
|
@@ -333,7 +343,13 @@ class Snapshot {
|
|
|
333
343
|
@public
|
|
334
344
|
*/
|
|
335
345
|
get record() {
|
|
336
|
-
|
|
346
|
+
const record = this._store.peekRecord(this.identifier);
|
|
347
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
348
|
+
if (!test) {
|
|
349
|
+
throw new Error(`Record ${this.identifier.type} ${this.identifier.id} (${this.identifier.lid}) is not yet loaded and thus cannot be accessed from the Snapshot during serialization`);
|
|
350
|
+
}
|
|
351
|
+
})(record !== null) : {};
|
|
352
|
+
return record;
|
|
337
353
|
}
|
|
338
354
|
get _attributes() {
|
|
339
355
|
if (this.__attributes !== null) {
|
|
@@ -343,10 +359,12 @@ class Snapshot {
|
|
|
343
359
|
const {
|
|
344
360
|
identifier
|
|
345
361
|
} = this;
|
|
346
|
-
const attrs =
|
|
362
|
+
const attrs = this._store.schema.fields(identifier);
|
|
347
363
|
const cache = this._store.cache;
|
|
348
|
-
attrs.forEach(keyName => {
|
|
349
|
-
|
|
364
|
+
attrs.forEach((field, keyName) => {
|
|
365
|
+
if (field.kind === 'attribute') {
|
|
366
|
+
attributes[keyName] = cache.getAttr(identifier, keyName);
|
|
367
|
+
}
|
|
350
368
|
});
|
|
351
369
|
return attributes;
|
|
352
370
|
}
|
|
@@ -373,7 +391,11 @@ class Snapshot {
|
|
|
373
391
|
if (keyName in this._attributes) {
|
|
374
392
|
return this._attributes[keyName];
|
|
375
393
|
}
|
|
376
|
-
|
|
394
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
395
|
+
{
|
|
396
|
+
throw new Error(`Model '${this.identifier.lid}' has no attribute named '${keyName}' defined.`);
|
|
397
|
+
}
|
|
398
|
+
})() : {};
|
|
377
399
|
}
|
|
378
400
|
|
|
379
401
|
/**
|
|
@@ -406,13 +428,13 @@ class Snapshot {
|
|
|
406
428
|
@public
|
|
407
429
|
*/
|
|
408
430
|
changedAttributes() {
|
|
409
|
-
|
|
431
|
+
const changedAttributes = Object.create(null);
|
|
410
432
|
if (!this._changedAttributes) {
|
|
411
433
|
return changedAttributes;
|
|
412
434
|
}
|
|
413
|
-
|
|
435
|
+
const changedAttributeKeys = Object.keys(this._changedAttributes);
|
|
414
436
|
for (let i = 0, length = changedAttributeKeys.length; i < length; i++) {
|
|
415
|
-
|
|
437
|
+
const key = changedAttributeKeys[i];
|
|
416
438
|
changedAttributes[key] = this._changedAttributes[key].slice();
|
|
417
439
|
}
|
|
418
440
|
return changedAttributes;
|
|
@@ -447,40 +469,48 @@ class Snapshot {
|
|
|
447
469
|
will be returned if the contents of the relationship is unknown.
|
|
448
470
|
*/
|
|
449
471
|
belongsTo(keyName, options) {
|
|
450
|
-
|
|
472
|
+
const returnModeIsId = !!(options && options.id);
|
|
451
473
|
let result;
|
|
452
|
-
|
|
474
|
+
const store = this._store;
|
|
453
475
|
if (returnModeIsId === true && keyName in this._belongsToIds) {
|
|
454
476
|
return this._belongsToIds[keyName];
|
|
455
477
|
}
|
|
456
478
|
if (returnModeIsId === false && keyName in this._belongsToRelationships) {
|
|
457
479
|
return this._belongsToRelationships[keyName];
|
|
458
480
|
}
|
|
459
|
-
|
|
481
|
+
const relationshipMeta = store.schema.fields({
|
|
460
482
|
type: this.modelName
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
}
|
|
483
|
+
}).get(keyName);
|
|
484
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
485
|
+
if (!test) {
|
|
486
|
+
throw new Error(`Model '${this.identifier.lid}' has no belongsTo relationship named '${keyName}' defined.`);
|
|
487
|
+
}
|
|
488
|
+
})(relationshipMeta && relationshipMeta.kind === 'belongsTo') : {};
|
|
489
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
490
|
+
if (!test) {
|
|
491
|
+
throw new Error(`snapshot.belongsTo only supported when using the package @ember-data/graph`);
|
|
492
|
+
}
|
|
493
|
+
})(dependencySatisfies('@ember-data/graph', '*')) : {};
|
|
472
494
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
473
495
|
const {
|
|
474
496
|
identifier
|
|
475
497
|
} = this;
|
|
476
|
-
if (macroCondition(
|
|
498
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
477
499
|
const relationship = graphFor(this._store).get(identifier, keyName);
|
|
478
|
-
|
|
479
|
-
|
|
500
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
501
|
+
if (!test) {
|
|
502
|
+
throw new Error(`You looked up the ${keyName} belongsTo relationship for { type: ${identifier.type}, id: ${identifier.id || ''}, lid: ${identifier.lid} but no such relationship was found.`);
|
|
503
|
+
}
|
|
504
|
+
})(relationship) : {};
|
|
505
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
506
|
+
if (!test) {
|
|
507
|
+
throw new Error(`You looked up the ${keyName} belongsTo relationship for { type: ${identifier.type}, id: ${identifier.id || ''}, lid: ${identifier.lid} but that relationship is a hasMany.`);
|
|
508
|
+
}
|
|
509
|
+
})(relationship.definition.kind === 'belongsTo') : {};
|
|
480
510
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
511
|
+
const value = graphFor(this._store).getData(identifier, keyName);
|
|
512
|
+
const data = value && value.data;
|
|
513
|
+
const inverseIdentifier = data ? store.identifierCache.getOrCreateRecordIdentifier(data) : null;
|
|
484
514
|
if (value && value.data !== undefined) {
|
|
485
515
|
const cache = store.cache;
|
|
486
516
|
if (inverseIdentifier && !cache.isDeleted(inverseIdentifier)) {
|
|
@@ -525,44 +555,58 @@ class Snapshot {
|
|
|
525
555
|
undefined will be returned if the contents of the relationship is unknown.
|
|
526
556
|
*/
|
|
527
557
|
hasMany(keyName, options) {
|
|
528
|
-
|
|
558
|
+
const returnModeIsIds = !!(options && options.ids);
|
|
529
559
|
let results;
|
|
530
|
-
|
|
531
|
-
|
|
560
|
+
const cachedIds = this._hasManyIds[keyName];
|
|
561
|
+
const cachedSnapshots = this._hasManyRelationships[keyName];
|
|
532
562
|
if (returnModeIsIds === true && keyName in this._hasManyIds) {
|
|
533
563
|
return cachedIds;
|
|
534
564
|
}
|
|
535
565
|
if (returnModeIsIds === false && keyName in this._hasManyRelationships) {
|
|
536
566
|
return cachedSnapshots;
|
|
537
567
|
}
|
|
538
|
-
|
|
539
|
-
|
|
568
|
+
const store = this._store;
|
|
569
|
+
const relationshipMeta = store.schema.fields({
|
|
540
570
|
type: this.modelName
|
|
541
|
-
})
|
|
542
|
-
|
|
571
|
+
}).get(keyName);
|
|
572
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
573
|
+
if (!test) {
|
|
574
|
+
throw new Error(`Model '${this.identifier.lid}' has no hasMany relationship named '${keyName}' defined.`);
|
|
575
|
+
}
|
|
576
|
+
})(relationshipMeta && relationshipMeta.kind === 'hasMany') : {};
|
|
543
577
|
|
|
544
578
|
// TODO @runspired it seems this code branch would not work with CUSTOM_MODEL_CLASSes
|
|
545
579
|
// this check is not a regression in behavior because relationships don't currently
|
|
546
580
|
// function without access to intimate API contracts between RecordData and Model.
|
|
547
581
|
// This is a requirement we should fix as soon as the relationship layer does not require
|
|
548
582
|
// this intimate API usage.
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
583
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
584
|
+
if (!test) {
|
|
585
|
+
throw new Error(`snapshot.hasMany only supported when using the package @ember-data/graph`);
|
|
586
|
+
}
|
|
587
|
+
})(dependencySatisfies('@ember-data/graph', '*')) : {};
|
|
552
588
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
553
589
|
const {
|
|
554
590
|
identifier
|
|
555
591
|
} = this;
|
|
556
|
-
if (macroCondition(
|
|
592
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
557
593
|
const relationship = graphFor(this._store).get(identifier, keyName);
|
|
558
|
-
|
|
559
|
-
|
|
594
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
595
|
+
if (!test) {
|
|
596
|
+
throw new Error(`You looked up the ${keyName} hasMany relationship for { type: ${identifier.type}, id: ${identifier.id || ''}, lid: ${identifier.lid} but no such relationship was found.`);
|
|
597
|
+
}
|
|
598
|
+
})(relationship) : {};
|
|
599
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
600
|
+
if (!test) {
|
|
601
|
+
throw new Error(`You looked up the ${keyName} hasMany relationship for { type: ${identifier.type}, id: ${identifier.id || ''}, lid: ${identifier.lid} but that relationship is a belongsTo.`);
|
|
602
|
+
}
|
|
603
|
+
})(relationship.definition.kind === 'hasMany') : {};
|
|
560
604
|
}
|
|
561
|
-
|
|
605
|
+
const value = graphFor(this._store).getData(identifier, keyName);
|
|
562
606
|
if (value.data) {
|
|
563
607
|
results = [];
|
|
564
608
|
value.data.forEach(member => {
|
|
565
|
-
|
|
609
|
+
const inverseIdentifier = store.identifierCache.getOrCreateRecordIdentifier(member);
|
|
566
610
|
const cache = store.cache;
|
|
567
611
|
if (!cache.isDeleted(inverseIdentifier)) {
|
|
568
612
|
if (returnModeIsIds) {
|
|
@@ -599,9 +643,11 @@ class Snapshot {
|
|
|
599
643
|
@public
|
|
600
644
|
*/
|
|
601
645
|
eachAttribute(callback, binding) {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
646
|
+
const fields = this._store.schema.fields(this.identifier);
|
|
647
|
+
fields.forEach((field, key) => {
|
|
648
|
+
if (field.kind === 'attribute') {
|
|
649
|
+
callback.call(binding, key, field);
|
|
650
|
+
}
|
|
605
651
|
});
|
|
606
652
|
}
|
|
607
653
|
|
|
@@ -620,9 +666,11 @@ class Snapshot {
|
|
|
620
666
|
@public
|
|
621
667
|
*/
|
|
622
668
|
eachRelationship(callback, binding) {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
669
|
+
const fields = this._store.schema.fields(this.identifier);
|
|
670
|
+
fields.forEach((field, key) => {
|
|
671
|
+
if (field.kind === 'belongsTo' || field.kind === 'hasMany') {
|
|
672
|
+
callback.call(binding, key, field);
|
|
673
|
+
}
|
|
626
674
|
});
|
|
627
675
|
}
|
|
628
676
|
|
|
@@ -648,12 +696,17 @@ class Snapshot {
|
|
|
648
696
|
@public
|
|
649
697
|
*/
|
|
650
698
|
serialize(options) {
|
|
699
|
+
upgradeStore(this._store);
|
|
651
700
|
const serializer = this._store.serializerFor(this.modelName);
|
|
652
|
-
|
|
701
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
702
|
+
if (!test) {
|
|
703
|
+
throw new Error(`Cannot serialize record, no serializer found`);
|
|
704
|
+
}
|
|
705
|
+
})(serializer) : {};
|
|
653
706
|
return serializer.serialize(this, options);
|
|
654
707
|
}
|
|
655
708
|
}
|
|
656
|
-
const SaveOp = Symbol('SaveOp');
|
|
709
|
+
const SaveOp = getOrSetGlobal('SaveOp', Symbol('SaveOp'));
|
|
657
710
|
class FetchManager {
|
|
658
711
|
// fetches pending in the runloop, waiting to be coalesced
|
|
659
712
|
|
|
@@ -675,13 +728,13 @@ class FetchManager {
|
|
|
675
728
|
@internal
|
|
676
729
|
*/
|
|
677
730
|
scheduleSave(identifier, options) {
|
|
678
|
-
|
|
679
|
-
|
|
731
|
+
const resolver = createDeferred();
|
|
732
|
+
const query = {
|
|
680
733
|
op: 'saveRecord',
|
|
681
734
|
recordIdentifier: identifier,
|
|
682
735
|
options
|
|
683
736
|
};
|
|
684
|
-
|
|
737
|
+
const queryRequest = {
|
|
685
738
|
data: [query]
|
|
686
739
|
};
|
|
687
740
|
const snapshot = this.createSnapshot(identifier, options);
|
|
@@ -697,19 +750,19 @@ class FetchManager {
|
|
|
697
750
|
return monitored;
|
|
698
751
|
}
|
|
699
752
|
scheduleFetch(identifier, options, request) {
|
|
700
|
-
|
|
753
|
+
const query = {
|
|
701
754
|
op: 'findRecord',
|
|
702
755
|
recordIdentifier: identifier,
|
|
703
756
|
options
|
|
704
757
|
};
|
|
705
|
-
|
|
758
|
+
const queryRequest = {
|
|
706
759
|
data: [query]
|
|
707
760
|
};
|
|
708
|
-
|
|
761
|
+
const pendingFetch = this.getPendingFetch(identifier, options);
|
|
709
762
|
if (pendingFetch) {
|
|
710
763
|
return pendingFetch;
|
|
711
764
|
}
|
|
712
|
-
|
|
765
|
+
const modelName = identifier.type;
|
|
713
766
|
const resolver = createDeferred();
|
|
714
767
|
const pendingFetchItem = {
|
|
715
768
|
identifier,
|
|
@@ -717,7 +770,7 @@ class FetchManager {
|
|
|
717
770
|
options,
|
|
718
771
|
queryRequest
|
|
719
772
|
};
|
|
720
|
-
|
|
773
|
+
const resolverPromise = resolver.promise;
|
|
721
774
|
const store = this._store;
|
|
722
775
|
const isInitialLoad = !store._instanceCache.recordIsLoaded(identifier); // we don't use isLoading directly because we are the request
|
|
723
776
|
|
|
@@ -730,17 +783,21 @@ class FetchManager {
|
|
|
730
783
|
|
|
731
784
|
// additional data received in the payload
|
|
732
785
|
// may result in the merging of identifiers (and thus records)
|
|
733
|
-
|
|
786
|
+
const potentiallyNewIm = store._push(payload, options.reload);
|
|
734
787
|
if (potentiallyNewIm && !Array.isArray(potentiallyNewIm)) {
|
|
735
788
|
return potentiallyNewIm;
|
|
736
789
|
}
|
|
737
790
|
return identifier;
|
|
738
791
|
}, error => {
|
|
739
|
-
|
|
792
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
793
|
+
if (!test) {
|
|
794
|
+
throw new Error(`Async Leak Detected: Expected the store to not be destroyed`);
|
|
795
|
+
}
|
|
796
|
+
})(!store.isDestroyed) : {};
|
|
740
797
|
const cache = store.cache;
|
|
741
798
|
if (!cache || cache.isEmpty(identifier) || isInitialLoad) {
|
|
742
799
|
let isReleasable = true;
|
|
743
|
-
if (macroCondition(
|
|
800
|
+
if (macroCondition(dependencySatisfies('@ember-data/graph', '*'))) {
|
|
744
801
|
if (!cache) {
|
|
745
802
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
746
803
|
const graph = graphFor(store);
|
|
@@ -763,7 +820,7 @@ class FetchManager {
|
|
|
763
820
|
this.flushAllPendingFetches();
|
|
764
821
|
});
|
|
765
822
|
}
|
|
766
|
-
|
|
823
|
+
const fetchesByType = this._pendingFetch;
|
|
767
824
|
let fetchesById = fetchesByType.get(modelName);
|
|
768
825
|
if (!fetchesById) {
|
|
769
826
|
fetchesById = new Map();
|
|
@@ -775,7 +832,7 @@ class FetchManager {
|
|
|
775
832
|
fetchesById.set(identifier, requestsForIdentifier);
|
|
776
833
|
}
|
|
777
834
|
requestsForIdentifier.push(pendingFetchItem);
|
|
778
|
-
if (macroCondition(
|
|
835
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.TESTING)) {
|
|
779
836
|
if (!request.disableTestWaiter) {
|
|
780
837
|
const {
|
|
781
838
|
waitForPromise
|
|
@@ -787,11 +844,11 @@ class FetchManager {
|
|
|
787
844
|
return promise;
|
|
788
845
|
}
|
|
789
846
|
getPendingFetch(identifier, options) {
|
|
790
|
-
|
|
847
|
+
const pendingFetches = this._pendingFetch.get(identifier.type)?.get(identifier);
|
|
791
848
|
|
|
792
849
|
// We already have a pending fetch for this
|
|
793
850
|
if (pendingFetches) {
|
|
794
|
-
|
|
851
|
+
const matchingPendingFetch = pendingFetches.find(fetch => isSameRequest(options, fetch.options));
|
|
795
852
|
if (matchingPendingFetch) {
|
|
796
853
|
return matchingPendingFetch.promise;
|
|
797
854
|
}
|
|
@@ -812,7 +869,7 @@ class FetchManager {
|
|
|
812
869
|
let promise;
|
|
813
870
|
if (isEmpty) {
|
|
814
871
|
assertIdentifierHasId(identifier);
|
|
815
|
-
if (macroCondition(
|
|
872
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
816
873
|
promise = this.scheduleFetch(identifier, Object.assign({}, options, {
|
|
817
874
|
reload: true
|
|
818
875
|
}), request);
|
|
@@ -822,7 +879,11 @@ class FetchManager {
|
|
|
822
879
|
}
|
|
823
880
|
} else if (isLoading) {
|
|
824
881
|
promise = this.getPendingFetch(identifier, options);
|
|
825
|
-
|
|
882
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
883
|
+
if (!test) {
|
|
884
|
+
throw new Error(`Expected to find a pending request for a record in the loading state, but found none`);
|
|
885
|
+
}
|
|
886
|
+
})(promise) : {};
|
|
826
887
|
} else {
|
|
827
888
|
promise = Promise.resolve(identifier);
|
|
828
889
|
}
|
|
@@ -887,27 +948,43 @@ function isSameRequest(options = {}, existingOptions = {}) {
|
|
|
887
948
|
return optionsSatisfies(options.adapterOptions, existingOptions.adapterOptions) && includesSatisfies(options.include, existingOptions.include);
|
|
888
949
|
}
|
|
889
950
|
function _findMany(store, adapter, modelName, snapshots) {
|
|
890
|
-
|
|
891
|
-
|
|
951
|
+
const modelClass = store.modelFor(modelName); // `adapter.findMany` gets the modelClass still
|
|
952
|
+
const promise = Promise.resolve().then(() => {
|
|
892
953
|
const ids = snapshots.map(s => s.id);
|
|
893
|
-
|
|
954
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
955
|
+
if (!test) {
|
|
956
|
+
throw new Error(`Cannot fetch a record without an id`);
|
|
957
|
+
}
|
|
958
|
+
})(ids.every(v => v !== null)) : {};
|
|
894
959
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
960
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
961
|
+
if (!test) {
|
|
962
|
+
throw new Error(`Expected this adapter to implement findMany for coalescing`);
|
|
963
|
+
}
|
|
964
|
+
})(adapter.findMany) : {};
|
|
965
|
+
const ret = adapter.findMany(store, modelClass, ids, snapshots);
|
|
966
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
967
|
+
if (!test) {
|
|
968
|
+
throw new Error('adapter.findMany returned undefined, this was very likely a mistake');
|
|
969
|
+
}
|
|
970
|
+
})(ret !== undefined) : {};
|
|
898
971
|
return ret;
|
|
899
972
|
});
|
|
900
973
|
return promise.then(adapterPayload => {
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
974
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
975
|
+
if (!test) {
|
|
976
|
+
throw new Error(`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`);
|
|
977
|
+
}
|
|
978
|
+
})(!!payloadIsNotBlank(adapterPayload)) : {};
|
|
979
|
+
const serializer = store.serializerFor(modelName);
|
|
980
|
+
const payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findMany');
|
|
904
981
|
return payload;
|
|
905
982
|
});
|
|
906
983
|
}
|
|
907
984
|
function rejectFetchedItems(fetchMap, snapshots, error) {
|
|
908
985
|
for (let i = 0, l = snapshots.length; i < l; i++) {
|
|
909
|
-
|
|
910
|
-
|
|
986
|
+
const snapshot = snapshots[i];
|
|
987
|
+
const pair = fetchMap.get(snapshot);
|
|
911
988
|
if (pair) {
|
|
912
989
|
pair.resolver.reject(error || new Error(`Expected: '<${snapshot.modelName}:${snapshot.id}>' to be present in the adapter provided payload, but it was not found.`));
|
|
913
990
|
}
|
|
@@ -923,9 +1000,9 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
923
1000
|
options object, we resolve all snapshots by id with
|
|
924
1001
|
the first response we see.
|
|
925
1002
|
*/
|
|
926
|
-
|
|
1003
|
+
const snapshotsById = new Map();
|
|
927
1004
|
for (let i = 0; i < snapshots.length; i++) {
|
|
928
|
-
|
|
1005
|
+
const id = snapshots[i].id;
|
|
929
1006
|
let snapshotGroup = snapshotsById.get(id);
|
|
930
1007
|
if (!snapshotGroup) {
|
|
931
1008
|
snapshotGroup = [];
|
|
@@ -936,18 +1013,18 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
936
1013
|
const included = Array.isArray(coalescedPayload.included) ? coalescedPayload.included : [];
|
|
937
1014
|
|
|
938
1015
|
// resolve found records
|
|
939
|
-
|
|
1016
|
+
const resources = coalescedPayload.data;
|
|
940
1017
|
for (let i = 0, l = resources.length; i < l; i++) {
|
|
941
|
-
|
|
942
|
-
|
|
1018
|
+
const resource = resources[i];
|
|
1019
|
+
const snapshotGroup = snapshotsById.get(resource.id);
|
|
943
1020
|
snapshotsById.delete(resource.id);
|
|
944
1021
|
if (!snapshotGroup) {
|
|
945
1022
|
// TODO consider whether this should be a deprecation/assertion
|
|
946
1023
|
included.push(resource);
|
|
947
1024
|
} else {
|
|
948
1025
|
snapshotGroup.forEach(snapshot => {
|
|
949
|
-
|
|
950
|
-
|
|
1026
|
+
const pair = fetchMap.get(snapshot);
|
|
1027
|
+
const resolver = pair.resolver;
|
|
951
1028
|
resolver.resolve({
|
|
952
1029
|
data: resource
|
|
953
1030
|
});
|
|
@@ -965,7 +1042,7 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
965
1042
|
}
|
|
966
1043
|
|
|
967
1044
|
// reject missing records
|
|
968
|
-
|
|
1045
|
+
const rejected = [];
|
|
969
1046
|
snapshotsById.forEach(snapshotArray => {
|
|
970
1047
|
rejected.push(...snapshotArray);
|
|
971
1048
|
});
|
|
@@ -975,23 +1052,47 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
975
1052
|
rejectFetchedItems(fetchMap, rejected);
|
|
976
1053
|
}
|
|
977
1054
|
function _fetchRecord(store, adapter, fetchItem) {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1055
|
+
const identifier = fetchItem.identifier;
|
|
1056
|
+
const modelName = identifier.type;
|
|
1057
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1058
|
+
if (!test) {
|
|
1059
|
+
throw new Error(`You tried to find a record but you have no adapter (for ${modelName})`);
|
|
1060
|
+
}
|
|
1061
|
+
})(adapter) : {};
|
|
1062
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1063
|
+
if (!test) {
|
|
1064
|
+
throw new Error(`You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`);
|
|
1065
|
+
}
|
|
1066
|
+
})(typeof adapter.findRecord === 'function') : {};
|
|
1067
|
+
const snapshot = store._fetchManager.createSnapshot(identifier, fetchItem.options);
|
|
1068
|
+
const klass = store.modelFor(identifier.type);
|
|
1069
|
+
const id = identifier.id;
|
|
985
1070
|
let promise = Promise.resolve().then(() => {
|
|
986
1071
|
return adapter.findRecord(store, klass, identifier.id, snapshot);
|
|
987
1072
|
});
|
|
988
1073
|
promise = promise.then(adapterPayload => {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1074
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1075
|
+
if (!test) {
|
|
1076
|
+
throw new Error(`Async Leak Detected: Expected the store to not be destroyed`);
|
|
1077
|
+
}
|
|
1078
|
+
})(!(store.isDestroyed || store.isDestroying)) : {};
|
|
1079
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1080
|
+
if (!test) {
|
|
1081
|
+
throw new Error(`You made a 'findRecord' request for a '${modelName}' with id '${id}', but the adapter's response did not have any data`);
|
|
1082
|
+
}
|
|
1083
|
+
})(!!payloadIsNotBlank(adapterPayload)) : {};
|
|
1084
|
+
const serializer = store.serializerFor(modelName);
|
|
1085
|
+
const payload = normalizeResponseHelper(serializer, store, klass, adapterPayload, id, 'findRecord');
|
|
1086
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1087
|
+
if (!test) {
|
|
1088
|
+
throw new Error(`Ember Data expected the primary data returned from a 'findRecord' response to be an object but instead it found an array.`);
|
|
1089
|
+
}
|
|
1090
|
+
})(!Array.isArray(payload.data)) : {};
|
|
1091
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1092
|
+
if (!test) {
|
|
1093
|
+
throw new Error(`The 'findRecord' request for ${modelName}:${id} resolved indicating success but contained no primary data. To indicate a 404 not found you should either reject the promise returned by the adapter's findRecord method or throw a NotFoundError.`);
|
|
1094
|
+
}
|
|
1095
|
+
})('data' in payload && payload.data !== null && typeof payload.data === 'object') : {};
|
|
995
1096
|
warn(`You requested a record of type '${modelName}' with id '${id}' but the adapter returned a payload with primary data having an id of '${payload.data.id}'. Use 'store.findRecord()' when the requested id is the same as the one returned by the adapter. In other cases use 'store.queryRecord()' instead.`, coerceId(payload.data.id) === coerceId(id), {
|
|
996
1097
|
id: 'ds.store.findRecord.id-mismatch'
|
|
997
1098
|
});
|
|
@@ -1009,12 +1110,16 @@ function _processCoalescedGroup(store, fetchMap, group, adapter, modelName) {
|
|
|
1009
1110
|
} else if (group.length === 1) {
|
|
1010
1111
|
_fetchRecord(store, adapter, fetchMap.get(group[0]));
|
|
1011
1112
|
} else {
|
|
1012
|
-
|
|
1113
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1114
|
+
{
|
|
1115
|
+
throw new Error("You cannot return an empty array from adapter's method groupRecordsForFindMany");
|
|
1116
|
+
}
|
|
1117
|
+
})() : {};
|
|
1013
1118
|
}
|
|
1014
1119
|
}
|
|
1015
1120
|
function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
1016
|
-
|
|
1017
|
-
|
|
1121
|
+
const adapter = store.adapterFor(modelName);
|
|
1122
|
+
const shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests;
|
|
1018
1123
|
if (shouldCoalesce) {
|
|
1019
1124
|
const pendingFetchItems = [];
|
|
1020
1125
|
pendingFetchMap.forEach((requestsForIdentifier, identifier) => {
|
|
@@ -1026,12 +1131,12 @@ function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
|
1026
1131
|
pendingFetchMap.delete(identifier);
|
|
1027
1132
|
pendingFetchItems.push(requestsForIdentifier[0]);
|
|
1028
1133
|
});
|
|
1029
|
-
|
|
1134
|
+
const totalItems = pendingFetchItems.length;
|
|
1030
1135
|
if (totalItems > 1) {
|
|
1031
|
-
|
|
1032
|
-
|
|
1136
|
+
const snapshots = new Array(totalItems);
|
|
1137
|
+
const fetchMap = new Map();
|
|
1033
1138
|
for (let i = 0; i < totalItems; i++) {
|
|
1034
|
-
|
|
1139
|
+
const fetchItem = pendingFetchItems[i];
|
|
1035
1140
|
snapshots[i] = store._fetchManager.createSnapshot(fetchItem.identifier, fetchItem.options);
|
|
1036
1141
|
fetchMap.set(snapshots[i], fetchItem);
|
|
1037
1142
|
}
|
|
@@ -1045,12 +1150,12 @@ function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
|
1045
1150
|
_processCoalescedGroup(store, fetchMap, groups[i], adapter, modelName);
|
|
1046
1151
|
}
|
|
1047
1152
|
} else if (totalItems === 1) {
|
|
1048
|
-
|
|
1153
|
+
_fetchRecord(store, adapter, pendingFetchItems[0]);
|
|
1049
1154
|
}
|
|
1050
1155
|
}
|
|
1051
1156
|
pendingFetchMap.forEach(pendingFetchItems => {
|
|
1052
1157
|
pendingFetchItems.forEach(pendingFetchItem => {
|
|
1053
|
-
|
|
1158
|
+
_fetchRecord(store, adapter, pendingFetchItem);
|
|
1054
1159
|
});
|
|
1055
1160
|
});
|
|
1056
1161
|
}
|
|
@@ -1063,13 +1168,25 @@ function _flushPendingSave(store, pending) {
|
|
|
1063
1168
|
} = pending;
|
|
1064
1169
|
const adapter = store.adapterFor(identifier.type);
|
|
1065
1170
|
const operation = options[SaveOp];
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1171
|
+
const modelName = snapshot.modelName;
|
|
1172
|
+
const modelClass = store.modelFor(modelName);
|
|
1173
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1174
|
+
if (!test) {
|
|
1175
|
+
throw new Error(`You tried to update a record but you have no adapter (for ${modelName})`);
|
|
1176
|
+
}
|
|
1177
|
+
})(adapter) : {};
|
|
1178
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1179
|
+
if (!test) {
|
|
1180
|
+
throw new Error(`You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`);
|
|
1181
|
+
}
|
|
1182
|
+
})(typeof adapter[operation] === 'function') : {};
|
|
1070
1183
|
let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot));
|
|
1071
|
-
|
|
1072
|
-
|
|
1184
|
+
const serializer = store.serializerFor(modelName);
|
|
1185
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1186
|
+
if (!test) {
|
|
1187
|
+
throw new Error(`Your adapter's '${operation}' method must return a value, but it returned 'undefined'`);
|
|
1188
|
+
}
|
|
1189
|
+
})(promise !== undefined) : {};
|
|
1073
1190
|
promise = promise.then(adapterPayload => {
|
|
1074
1191
|
if (adapterPayload) {
|
|
1075
1192
|
return normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation);
|
|
@@ -1077,4 +1194,13 @@ function _flushPendingSave(store, pending) {
|
|
|
1077
1194
|
});
|
|
1078
1195
|
resolver.resolve(promise);
|
|
1079
1196
|
}
|
|
1080
|
-
|
|
1197
|
+
|
|
1198
|
+
/**
|
|
1199
|
+
* Utilities - often temporary - for maintaining backwards compatibility with
|
|
1200
|
+
* older parts of EmberData.
|
|
1201
|
+
*
|
|
1202
|
+
@module @ember-data/legacy-compat
|
|
1203
|
+
@main @ember-data/legacy-compat
|
|
1204
|
+
*/
|
|
1205
|
+
function upgradeStore(store) {}
|
|
1206
|
+
export { FetchManager as F, SaveOp as S, assertIdentifierHasId as a, SnapshotRecordArray as b, Snapshot as c, iterateData as i, normalizeResponseHelper as n, payloadIsNotBlank as p, upgradeStore as u };
|