@ember-data/legacy-compat 5.5.0-alpha.11 → 5.5.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/LICENSE.md +19 -7
- package/README.md +10 -2
- package/addon-main.cjs +5 -0
- package/{addon/fetch-manager-c66055fb.js → dist/-private-Dlia0pw1.js} +250 -125
- package/dist/-private-Dlia0pw1.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 +1011 -0
- package/dist/index.js.map +1 -0
- package/dist/utils.js +246 -0
- package/dist/utils.js.map +1 -0
- package/logos/NCC-1701-a-blue.svg +4 -0
- package/logos/NCC-1701-a-gold.svg +4 -0
- package/logos/NCC-1701-a-gold_100.svg +1 -0
- package/logos/NCC-1701-a-gold_base-64.txt +1 -0
- package/logos/NCC-1701-a.svg +4 -0
- package/logos/README.md +4 -0
- package/logos/docs-badge.svg +2 -0
- package/logos/github-header.svg +444 -0
- package/logos/social1.png +0 -0
- package/logos/social2.png +0 -0
- package/logos/warp-drive-logo-dark.svg +4 -0
- package/logos/warp-drive-logo-gold.svg +4 -0
- package/package.json +59 -49
- 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-c66055fb.js.map +0 -1
- package/addon/index.js +0 -608
- package/addon/index.js.map +0 -1
- package/addon-main.js +0 -93
- /package/{addon → dist}/-private.js.map +0 -0
- /package/{ember-data-logo-dark.svg → logos/ember-data-logo-dark.svg} +0 -0
- /package/{ember-data-logo-light.svg → logos/ember-data-logo-light.svg} +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
|
}
|
|
@@ -275,6 +285,7 @@ class Snapshot {
|
|
|
275
285
|
the values.
|
|
276
286
|
*/
|
|
277
287
|
if (hasRecord) {
|
|
288
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
278
289
|
this._attributes;
|
|
279
290
|
}
|
|
280
291
|
|
|
@@ -334,7 +345,11 @@ class Snapshot {
|
|
|
334
345
|
*/
|
|
335
346
|
get record() {
|
|
336
347
|
const record = this._store.peekRecord(this.identifier);
|
|
337
|
-
|
|
348
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
349
|
+
if (!test) {
|
|
350
|
+
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`);
|
|
351
|
+
}
|
|
352
|
+
})(record !== null) : {};
|
|
338
353
|
return record;
|
|
339
354
|
}
|
|
340
355
|
get _attributes() {
|
|
@@ -345,10 +360,12 @@ class Snapshot {
|
|
|
345
360
|
const {
|
|
346
361
|
identifier
|
|
347
362
|
} = this;
|
|
348
|
-
const attrs =
|
|
363
|
+
const attrs = this._store.schema.fields(identifier);
|
|
349
364
|
const cache = this._store.cache;
|
|
350
|
-
attrs.forEach(keyName => {
|
|
351
|
-
|
|
365
|
+
attrs.forEach((field, keyName) => {
|
|
366
|
+
if (field.kind === 'attribute') {
|
|
367
|
+
attributes[keyName] = cache.getAttr(identifier, keyName);
|
|
368
|
+
}
|
|
352
369
|
});
|
|
353
370
|
return attributes;
|
|
354
371
|
}
|
|
@@ -375,7 +392,11 @@ class Snapshot {
|
|
|
375
392
|
if (keyName in this._attributes) {
|
|
376
393
|
return this._attributes[keyName];
|
|
377
394
|
}
|
|
378
|
-
|
|
395
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
396
|
+
{
|
|
397
|
+
throw new Error(`Model '${this.identifier.lid}' has no attribute named '${keyName}' defined.`);
|
|
398
|
+
}
|
|
399
|
+
})() : {};
|
|
379
400
|
}
|
|
380
401
|
|
|
381
402
|
/**
|
|
@@ -408,13 +429,13 @@ class Snapshot {
|
|
|
408
429
|
@public
|
|
409
430
|
*/
|
|
410
431
|
changedAttributes() {
|
|
411
|
-
|
|
432
|
+
const changedAttributes = Object.create(null);
|
|
412
433
|
if (!this._changedAttributes) {
|
|
413
434
|
return changedAttributes;
|
|
414
435
|
}
|
|
415
|
-
|
|
436
|
+
const changedAttributeKeys = Object.keys(this._changedAttributes);
|
|
416
437
|
for (let i = 0, length = changedAttributeKeys.length; i < length; i++) {
|
|
417
|
-
|
|
438
|
+
const key = changedAttributeKeys[i];
|
|
418
439
|
changedAttributes[key] = this._changedAttributes[key].slice();
|
|
419
440
|
}
|
|
420
441
|
return changedAttributes;
|
|
@@ -449,40 +470,48 @@ class Snapshot {
|
|
|
449
470
|
will be returned if the contents of the relationship is unknown.
|
|
450
471
|
*/
|
|
451
472
|
belongsTo(keyName, options) {
|
|
452
|
-
|
|
473
|
+
const returnModeIsId = !!(options && options.id);
|
|
453
474
|
let result;
|
|
454
|
-
|
|
475
|
+
const store = this._store;
|
|
455
476
|
if (returnModeIsId === true && keyName in this._belongsToIds) {
|
|
456
477
|
return this._belongsToIds[keyName];
|
|
457
478
|
}
|
|
458
479
|
if (returnModeIsId === false && keyName in this._belongsToRelationships) {
|
|
459
480
|
return this._belongsToRelationships[keyName];
|
|
460
481
|
}
|
|
461
|
-
|
|
482
|
+
const relationshipMeta = store.schema.fields({
|
|
462
483
|
type: this.modelName
|
|
463
|
-
})
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
}
|
|
484
|
+
}).get(keyName);
|
|
485
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
486
|
+
if (!test) {
|
|
487
|
+
throw new Error(`Model '${this.identifier.lid}' has no belongsTo relationship named '${keyName}' defined.`);
|
|
488
|
+
}
|
|
489
|
+
})(relationshipMeta && relationshipMeta.kind === 'belongsTo') : {};
|
|
490
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
491
|
+
if (!test) {
|
|
492
|
+
throw new Error(`snapshot.belongsTo only supported when using the package @ember-data/graph`);
|
|
493
|
+
}
|
|
494
|
+
})(dependencySatisfies('@ember-data/graph', '*')) : {};
|
|
474
495
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
475
496
|
const {
|
|
476
497
|
identifier
|
|
477
498
|
} = this;
|
|
478
|
-
if (macroCondition(
|
|
499
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
479
500
|
const relationship = graphFor(this._store).get(identifier, keyName);
|
|
480
|
-
|
|
481
|
-
|
|
501
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
502
|
+
if (!test) {
|
|
503
|
+
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.`);
|
|
504
|
+
}
|
|
505
|
+
})(relationship) : {};
|
|
506
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
507
|
+
if (!test) {
|
|
508
|
+
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.`);
|
|
509
|
+
}
|
|
510
|
+
})(relationship.definition.kind === 'belongsTo') : {};
|
|
482
511
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
512
|
+
const value = graphFor(this._store).getData(identifier, keyName);
|
|
513
|
+
const data = value && value.data;
|
|
514
|
+
const inverseIdentifier = data ? store.identifierCache.getOrCreateRecordIdentifier(data) : null;
|
|
486
515
|
if (value && value.data !== undefined) {
|
|
487
516
|
const cache = store.cache;
|
|
488
517
|
if (inverseIdentifier && !cache.isDeleted(inverseIdentifier)) {
|
|
@@ -527,44 +556,58 @@ class Snapshot {
|
|
|
527
556
|
undefined will be returned if the contents of the relationship is unknown.
|
|
528
557
|
*/
|
|
529
558
|
hasMany(keyName, options) {
|
|
530
|
-
|
|
559
|
+
const returnModeIsIds = !!(options && options.ids);
|
|
531
560
|
let results;
|
|
532
|
-
|
|
533
|
-
|
|
561
|
+
const cachedIds = this._hasManyIds[keyName];
|
|
562
|
+
const cachedSnapshots = this._hasManyRelationships[keyName];
|
|
534
563
|
if (returnModeIsIds === true && keyName in this._hasManyIds) {
|
|
535
564
|
return cachedIds;
|
|
536
565
|
}
|
|
537
566
|
if (returnModeIsIds === false && keyName in this._hasManyRelationships) {
|
|
538
567
|
return cachedSnapshots;
|
|
539
568
|
}
|
|
540
|
-
|
|
541
|
-
|
|
569
|
+
const store = this._store;
|
|
570
|
+
const relationshipMeta = store.schema.fields({
|
|
542
571
|
type: this.modelName
|
|
543
|
-
})
|
|
544
|
-
|
|
572
|
+
}).get(keyName);
|
|
573
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
574
|
+
if (!test) {
|
|
575
|
+
throw new Error(`Model '${this.identifier.lid}' has no hasMany relationship named '${keyName}' defined.`);
|
|
576
|
+
}
|
|
577
|
+
})(relationshipMeta && relationshipMeta.kind === 'hasMany') : {};
|
|
545
578
|
|
|
546
579
|
// TODO @runspired it seems this code branch would not work with CUSTOM_MODEL_CLASSes
|
|
547
580
|
// this check is not a regression in behavior because relationships don't currently
|
|
548
581
|
// function without access to intimate API contracts between RecordData and Model.
|
|
549
582
|
// This is a requirement we should fix as soon as the relationship layer does not require
|
|
550
583
|
// this intimate API usage.
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
584
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
585
|
+
if (!test) {
|
|
586
|
+
throw new Error(`snapshot.hasMany only supported when using the package @ember-data/graph`);
|
|
587
|
+
}
|
|
588
|
+
})(dependencySatisfies('@ember-data/graph', '*')) : {};
|
|
554
589
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
555
590
|
const {
|
|
556
591
|
identifier
|
|
557
592
|
} = this;
|
|
558
|
-
if (macroCondition(
|
|
593
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
559
594
|
const relationship = graphFor(this._store).get(identifier, keyName);
|
|
560
|
-
|
|
561
|
-
|
|
595
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
596
|
+
if (!test) {
|
|
597
|
+
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.`);
|
|
598
|
+
}
|
|
599
|
+
})(relationship) : {};
|
|
600
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
601
|
+
if (!test) {
|
|
602
|
+
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.`);
|
|
603
|
+
}
|
|
604
|
+
})(relationship.definition.kind === 'hasMany') : {};
|
|
562
605
|
}
|
|
563
|
-
|
|
606
|
+
const value = graphFor(this._store).getData(identifier, keyName);
|
|
564
607
|
if (value.data) {
|
|
565
608
|
results = [];
|
|
566
609
|
value.data.forEach(member => {
|
|
567
|
-
|
|
610
|
+
const inverseIdentifier = store.identifierCache.getOrCreateRecordIdentifier(member);
|
|
568
611
|
const cache = store.cache;
|
|
569
612
|
if (!cache.isDeleted(inverseIdentifier)) {
|
|
570
613
|
if (returnModeIsIds) {
|
|
@@ -601,9 +644,11 @@ class Snapshot {
|
|
|
601
644
|
@public
|
|
602
645
|
*/
|
|
603
646
|
eachAttribute(callback, binding) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
647
|
+
const fields = this._store.schema.fields(this.identifier);
|
|
648
|
+
fields.forEach((field, key) => {
|
|
649
|
+
if (field.kind === 'attribute') {
|
|
650
|
+
callback.call(binding, key, field);
|
|
651
|
+
}
|
|
607
652
|
});
|
|
608
653
|
}
|
|
609
654
|
|
|
@@ -622,9 +667,11 @@ class Snapshot {
|
|
|
622
667
|
@public
|
|
623
668
|
*/
|
|
624
669
|
eachRelationship(callback, binding) {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
670
|
+
const fields = this._store.schema.fields(this.identifier);
|
|
671
|
+
fields.forEach((field, key) => {
|
|
672
|
+
if (field.kind === 'belongsTo' || field.kind === 'hasMany') {
|
|
673
|
+
callback.call(binding, key, field);
|
|
674
|
+
}
|
|
628
675
|
});
|
|
629
676
|
}
|
|
630
677
|
|
|
@@ -650,12 +697,17 @@ class Snapshot {
|
|
|
650
697
|
@public
|
|
651
698
|
*/
|
|
652
699
|
serialize(options) {
|
|
700
|
+
upgradeStore(this._store);
|
|
653
701
|
const serializer = this._store.serializerFor(this.modelName);
|
|
654
|
-
|
|
702
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
703
|
+
if (!test) {
|
|
704
|
+
throw new Error(`Cannot serialize record, no serializer found`);
|
|
705
|
+
}
|
|
706
|
+
})(serializer) : {};
|
|
655
707
|
return serializer.serialize(this, options);
|
|
656
708
|
}
|
|
657
709
|
}
|
|
658
|
-
const SaveOp = Symbol('SaveOp');
|
|
710
|
+
const SaveOp = getOrSetGlobal('SaveOp', Symbol('SaveOp'));
|
|
659
711
|
class FetchManager {
|
|
660
712
|
// fetches pending in the runloop, waiting to be coalesced
|
|
661
713
|
|
|
@@ -677,13 +729,13 @@ class FetchManager {
|
|
|
677
729
|
@internal
|
|
678
730
|
*/
|
|
679
731
|
scheduleSave(identifier, options) {
|
|
680
|
-
|
|
681
|
-
|
|
732
|
+
const resolver = createDeferred();
|
|
733
|
+
const query = {
|
|
682
734
|
op: 'saveRecord',
|
|
683
735
|
recordIdentifier: identifier,
|
|
684
736
|
options
|
|
685
737
|
};
|
|
686
|
-
|
|
738
|
+
const queryRequest = {
|
|
687
739
|
data: [query]
|
|
688
740
|
};
|
|
689
741
|
const snapshot = this.createSnapshot(identifier, options);
|
|
@@ -699,19 +751,19 @@ class FetchManager {
|
|
|
699
751
|
return monitored;
|
|
700
752
|
}
|
|
701
753
|
scheduleFetch(identifier, options, request) {
|
|
702
|
-
|
|
754
|
+
const query = {
|
|
703
755
|
op: 'findRecord',
|
|
704
756
|
recordIdentifier: identifier,
|
|
705
757
|
options
|
|
706
758
|
};
|
|
707
|
-
|
|
759
|
+
const queryRequest = {
|
|
708
760
|
data: [query]
|
|
709
761
|
};
|
|
710
|
-
|
|
762
|
+
const pendingFetch = this.getPendingFetch(identifier, options);
|
|
711
763
|
if (pendingFetch) {
|
|
712
764
|
return pendingFetch;
|
|
713
765
|
}
|
|
714
|
-
|
|
766
|
+
const modelName = identifier.type;
|
|
715
767
|
const resolver = createDeferred();
|
|
716
768
|
const pendingFetchItem = {
|
|
717
769
|
identifier,
|
|
@@ -719,7 +771,7 @@ class FetchManager {
|
|
|
719
771
|
options,
|
|
720
772
|
queryRequest
|
|
721
773
|
};
|
|
722
|
-
|
|
774
|
+
const resolverPromise = resolver.promise;
|
|
723
775
|
const store = this._store;
|
|
724
776
|
const isInitialLoad = !store._instanceCache.recordIsLoaded(identifier); // we don't use isLoading directly because we are the request
|
|
725
777
|
|
|
@@ -732,17 +784,21 @@ class FetchManager {
|
|
|
732
784
|
|
|
733
785
|
// additional data received in the payload
|
|
734
786
|
// may result in the merging of identifiers (and thus records)
|
|
735
|
-
|
|
787
|
+
const potentiallyNewIm = store._push(payload, options.reload);
|
|
736
788
|
if (potentiallyNewIm && !Array.isArray(potentiallyNewIm)) {
|
|
737
789
|
return potentiallyNewIm;
|
|
738
790
|
}
|
|
739
791
|
return identifier;
|
|
740
792
|
}, error => {
|
|
741
|
-
|
|
793
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
794
|
+
if (!test) {
|
|
795
|
+
throw new Error(`Async Leak Detected: Expected the store to not be destroyed`);
|
|
796
|
+
}
|
|
797
|
+
})(!store.isDestroyed) : {};
|
|
742
798
|
const cache = store.cache;
|
|
743
799
|
if (!cache || cache.isEmpty(identifier) || isInitialLoad) {
|
|
744
800
|
let isReleasable = true;
|
|
745
|
-
if (macroCondition(
|
|
801
|
+
if (macroCondition(dependencySatisfies('@ember-data/graph', '*'))) {
|
|
746
802
|
if (!cache) {
|
|
747
803
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
748
804
|
const graph = graphFor(store);
|
|
@@ -765,7 +821,7 @@ class FetchManager {
|
|
|
765
821
|
this.flushAllPendingFetches();
|
|
766
822
|
});
|
|
767
823
|
}
|
|
768
|
-
|
|
824
|
+
const fetchesByType = this._pendingFetch;
|
|
769
825
|
let fetchesById = fetchesByType.get(modelName);
|
|
770
826
|
if (!fetchesById) {
|
|
771
827
|
fetchesById = new Map();
|
|
@@ -777,7 +833,7 @@ class FetchManager {
|
|
|
777
833
|
fetchesById.set(identifier, requestsForIdentifier);
|
|
778
834
|
}
|
|
779
835
|
requestsForIdentifier.push(pendingFetchItem);
|
|
780
|
-
if (macroCondition(
|
|
836
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.TESTING)) {
|
|
781
837
|
if (!request.disableTestWaiter) {
|
|
782
838
|
const {
|
|
783
839
|
waitForPromise
|
|
@@ -789,11 +845,11 @@ class FetchManager {
|
|
|
789
845
|
return promise;
|
|
790
846
|
}
|
|
791
847
|
getPendingFetch(identifier, options) {
|
|
792
|
-
|
|
848
|
+
const pendingFetches = this._pendingFetch.get(identifier.type)?.get(identifier);
|
|
793
849
|
|
|
794
850
|
// We already have a pending fetch for this
|
|
795
851
|
if (pendingFetches) {
|
|
796
|
-
|
|
852
|
+
const matchingPendingFetch = pendingFetches.find(fetch => isSameRequest(options, fetch.options));
|
|
797
853
|
if (matchingPendingFetch) {
|
|
798
854
|
return matchingPendingFetch.promise;
|
|
799
855
|
}
|
|
@@ -814,7 +870,7 @@ class FetchManager {
|
|
|
814
870
|
let promise;
|
|
815
871
|
if (isEmpty) {
|
|
816
872
|
assertIdentifierHasId(identifier);
|
|
817
|
-
if (macroCondition(
|
|
873
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
818
874
|
promise = this.scheduleFetch(identifier, Object.assign({}, options, {
|
|
819
875
|
reload: true
|
|
820
876
|
}), request);
|
|
@@ -824,7 +880,11 @@ class FetchManager {
|
|
|
824
880
|
}
|
|
825
881
|
} else if (isLoading) {
|
|
826
882
|
promise = this.getPendingFetch(identifier, options);
|
|
827
|
-
|
|
883
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
884
|
+
if (!test) {
|
|
885
|
+
throw new Error(`Expected to find a pending request for a record in the loading state, but found none`);
|
|
886
|
+
}
|
|
887
|
+
})(promise) : {};
|
|
828
888
|
} else {
|
|
829
889
|
promise = Promise.resolve(identifier);
|
|
830
890
|
}
|
|
@@ -889,27 +949,43 @@ function isSameRequest(options = {}, existingOptions = {}) {
|
|
|
889
949
|
return optionsSatisfies(options.adapterOptions, existingOptions.adapterOptions) && includesSatisfies(options.include, existingOptions.include);
|
|
890
950
|
}
|
|
891
951
|
function _findMany(store, adapter, modelName, snapshots) {
|
|
892
|
-
|
|
893
|
-
|
|
952
|
+
const modelClass = store.modelFor(modelName); // `adapter.findMany` gets the modelClass still
|
|
953
|
+
const promise = Promise.resolve().then(() => {
|
|
894
954
|
const ids = snapshots.map(s => s.id);
|
|
895
|
-
|
|
955
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
956
|
+
if (!test) {
|
|
957
|
+
throw new Error(`Cannot fetch a record without an id`);
|
|
958
|
+
}
|
|
959
|
+
})(ids.every(v => v !== null)) : {};
|
|
896
960
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
961
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
962
|
+
if (!test) {
|
|
963
|
+
throw new Error(`Expected this adapter to implement findMany for coalescing`);
|
|
964
|
+
}
|
|
965
|
+
})(adapter.findMany) : {};
|
|
966
|
+
const ret = adapter.findMany(store, modelClass, ids, snapshots);
|
|
967
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
968
|
+
if (!test) {
|
|
969
|
+
throw new Error('adapter.findMany returned undefined, this was very likely a mistake');
|
|
970
|
+
}
|
|
971
|
+
})(ret !== undefined) : {};
|
|
900
972
|
return ret;
|
|
901
973
|
});
|
|
902
974
|
return promise.then(adapterPayload => {
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
975
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
976
|
+
if (!test) {
|
|
977
|
+
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`);
|
|
978
|
+
}
|
|
979
|
+
})(!!payloadIsNotBlank(adapterPayload)) : {};
|
|
980
|
+
const serializer = store.serializerFor(modelName);
|
|
981
|
+
const payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findMany');
|
|
906
982
|
return payload;
|
|
907
983
|
});
|
|
908
984
|
}
|
|
909
985
|
function rejectFetchedItems(fetchMap, snapshots, error) {
|
|
910
986
|
for (let i = 0, l = snapshots.length; i < l; i++) {
|
|
911
|
-
|
|
912
|
-
|
|
987
|
+
const snapshot = snapshots[i];
|
|
988
|
+
const pair = fetchMap.get(snapshot);
|
|
913
989
|
if (pair) {
|
|
914
990
|
pair.resolver.reject(error || new Error(`Expected: '<${snapshot.modelName}:${snapshot.id}>' to be present in the adapter provided payload, but it was not found.`));
|
|
915
991
|
}
|
|
@@ -925,9 +1001,9 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
925
1001
|
options object, we resolve all snapshots by id with
|
|
926
1002
|
the first response we see.
|
|
927
1003
|
*/
|
|
928
|
-
|
|
1004
|
+
const snapshotsById = new Map();
|
|
929
1005
|
for (let i = 0; i < snapshots.length; i++) {
|
|
930
|
-
|
|
1006
|
+
const id = snapshots[i].id;
|
|
931
1007
|
let snapshotGroup = snapshotsById.get(id);
|
|
932
1008
|
if (!snapshotGroup) {
|
|
933
1009
|
snapshotGroup = [];
|
|
@@ -938,18 +1014,18 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
938
1014
|
const included = Array.isArray(coalescedPayload.included) ? coalescedPayload.included : [];
|
|
939
1015
|
|
|
940
1016
|
// resolve found records
|
|
941
|
-
|
|
1017
|
+
const resources = coalescedPayload.data;
|
|
942
1018
|
for (let i = 0, l = resources.length; i < l; i++) {
|
|
943
|
-
|
|
944
|
-
|
|
1019
|
+
const resource = resources[i];
|
|
1020
|
+
const snapshotGroup = snapshotsById.get(resource.id);
|
|
945
1021
|
snapshotsById.delete(resource.id);
|
|
946
1022
|
if (!snapshotGroup) {
|
|
947
1023
|
// TODO consider whether this should be a deprecation/assertion
|
|
948
1024
|
included.push(resource);
|
|
949
1025
|
} else {
|
|
950
1026
|
snapshotGroup.forEach(snapshot => {
|
|
951
|
-
|
|
952
|
-
|
|
1027
|
+
const pair = fetchMap.get(snapshot);
|
|
1028
|
+
const resolver = pair.resolver;
|
|
953
1029
|
resolver.resolve({
|
|
954
1030
|
data: resource
|
|
955
1031
|
});
|
|
@@ -967,7 +1043,7 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
967
1043
|
}
|
|
968
1044
|
|
|
969
1045
|
// reject missing records
|
|
970
|
-
|
|
1046
|
+
const rejected = [];
|
|
971
1047
|
snapshotsById.forEach(snapshotArray => {
|
|
972
1048
|
rejected.push(...snapshotArray);
|
|
973
1049
|
});
|
|
@@ -977,23 +1053,47 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
977
1053
|
rejectFetchedItems(fetchMap, rejected);
|
|
978
1054
|
}
|
|
979
1055
|
function _fetchRecord(store, adapter, fetchItem) {
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1056
|
+
const identifier = fetchItem.identifier;
|
|
1057
|
+
const modelName = identifier.type;
|
|
1058
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1059
|
+
if (!test) {
|
|
1060
|
+
throw new Error(`You tried to find a record but you have no adapter (for ${modelName})`);
|
|
1061
|
+
}
|
|
1062
|
+
})(adapter) : {};
|
|
1063
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1064
|
+
if (!test) {
|
|
1065
|
+
throw new Error(`You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`);
|
|
1066
|
+
}
|
|
1067
|
+
})(typeof adapter.findRecord === 'function') : {};
|
|
1068
|
+
const snapshot = store._fetchManager.createSnapshot(identifier, fetchItem.options);
|
|
1069
|
+
const klass = store.modelFor(identifier.type);
|
|
1070
|
+
const id = identifier.id;
|
|
987
1071
|
let promise = Promise.resolve().then(() => {
|
|
988
1072
|
return adapter.findRecord(store, klass, identifier.id, snapshot);
|
|
989
1073
|
});
|
|
990
1074
|
promise = promise.then(adapterPayload => {
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1075
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1076
|
+
if (!test) {
|
|
1077
|
+
throw new Error(`Async Leak Detected: Expected the store to not be destroyed`);
|
|
1078
|
+
}
|
|
1079
|
+
})(!(store.isDestroyed || store.isDestroying)) : {};
|
|
1080
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1081
|
+
if (!test) {
|
|
1082
|
+
throw new Error(`You made a 'findRecord' request for a '${modelName}' with id '${id}', but the adapter's response did not have any data`);
|
|
1083
|
+
}
|
|
1084
|
+
})(!!payloadIsNotBlank(adapterPayload)) : {};
|
|
1085
|
+
const serializer = store.serializerFor(modelName);
|
|
1086
|
+
const payload = normalizeResponseHelper(serializer, store, klass, adapterPayload, id, 'findRecord');
|
|
1087
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1088
|
+
if (!test) {
|
|
1089
|
+
throw new Error(`Ember Data expected the primary data returned from a 'findRecord' response to be an object but instead it found an array.`);
|
|
1090
|
+
}
|
|
1091
|
+
})(!Array.isArray(payload.data)) : {};
|
|
1092
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1093
|
+
if (!test) {
|
|
1094
|
+
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.`);
|
|
1095
|
+
}
|
|
1096
|
+
})('data' in payload && payload.data !== null && typeof payload.data === 'object') : {};
|
|
997
1097
|
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), {
|
|
998
1098
|
id: 'ds.store.findRecord.id-mismatch'
|
|
999
1099
|
});
|
|
@@ -1011,12 +1111,16 @@ function _processCoalescedGroup(store, fetchMap, group, adapter, modelName) {
|
|
|
1011
1111
|
} else if (group.length === 1) {
|
|
1012
1112
|
_fetchRecord(store, adapter, fetchMap.get(group[0]));
|
|
1013
1113
|
} else {
|
|
1014
|
-
|
|
1114
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1115
|
+
{
|
|
1116
|
+
throw new Error("You cannot return an empty array from adapter's method groupRecordsForFindMany");
|
|
1117
|
+
}
|
|
1118
|
+
})() : {};
|
|
1015
1119
|
}
|
|
1016
1120
|
}
|
|
1017
1121
|
function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
1018
|
-
|
|
1019
|
-
|
|
1122
|
+
const adapter = store.adapterFor(modelName);
|
|
1123
|
+
const shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests;
|
|
1020
1124
|
if (shouldCoalesce) {
|
|
1021
1125
|
const pendingFetchItems = [];
|
|
1022
1126
|
pendingFetchMap.forEach((requestsForIdentifier, identifier) => {
|
|
@@ -1028,12 +1132,12 @@ function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
|
1028
1132
|
pendingFetchMap.delete(identifier);
|
|
1029
1133
|
pendingFetchItems.push(requestsForIdentifier[0]);
|
|
1030
1134
|
});
|
|
1031
|
-
|
|
1135
|
+
const totalItems = pendingFetchItems.length;
|
|
1032
1136
|
if (totalItems > 1) {
|
|
1033
|
-
|
|
1034
|
-
|
|
1137
|
+
const snapshots = new Array(totalItems);
|
|
1138
|
+
const fetchMap = new Map();
|
|
1035
1139
|
for (let i = 0; i < totalItems; i++) {
|
|
1036
|
-
|
|
1140
|
+
const fetchItem = pendingFetchItems[i];
|
|
1037
1141
|
snapshots[i] = store._fetchManager.createSnapshot(fetchItem.identifier, fetchItem.options);
|
|
1038
1142
|
fetchMap.set(snapshots[i], fetchItem);
|
|
1039
1143
|
}
|
|
@@ -1047,12 +1151,12 @@ function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
|
1047
1151
|
_processCoalescedGroup(store, fetchMap, groups[i], adapter, modelName);
|
|
1048
1152
|
}
|
|
1049
1153
|
} else if (totalItems === 1) {
|
|
1050
|
-
|
|
1154
|
+
_fetchRecord(store, adapter, pendingFetchItems[0]);
|
|
1051
1155
|
}
|
|
1052
1156
|
}
|
|
1053
1157
|
pendingFetchMap.forEach(pendingFetchItems => {
|
|
1054
1158
|
pendingFetchItems.forEach(pendingFetchItem => {
|
|
1055
|
-
|
|
1159
|
+
_fetchRecord(store, adapter, pendingFetchItem);
|
|
1056
1160
|
});
|
|
1057
1161
|
});
|
|
1058
1162
|
}
|
|
@@ -1065,13 +1169,25 @@ function _flushPendingSave(store, pending) {
|
|
|
1065
1169
|
} = pending;
|
|
1066
1170
|
const adapter = store.adapterFor(identifier.type);
|
|
1067
1171
|
const operation = options[SaveOp];
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1172
|
+
const modelName = snapshot.modelName;
|
|
1173
|
+
const modelClass = store.modelFor(modelName);
|
|
1174
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1175
|
+
if (!test) {
|
|
1176
|
+
throw new Error(`You tried to update a record but you have no adapter (for ${modelName})`);
|
|
1177
|
+
}
|
|
1178
|
+
})(adapter) : {};
|
|
1179
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1180
|
+
if (!test) {
|
|
1181
|
+
throw new Error(`You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`);
|
|
1182
|
+
}
|
|
1183
|
+
})(typeof adapter[operation] === 'function') : {};
|
|
1072
1184
|
let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot));
|
|
1073
|
-
|
|
1074
|
-
|
|
1185
|
+
const serializer = store.serializerFor(modelName);
|
|
1186
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1187
|
+
if (!test) {
|
|
1188
|
+
throw new Error(`Your adapter's '${operation}' method must return a value, but it returned 'undefined'`);
|
|
1189
|
+
}
|
|
1190
|
+
})(promise !== undefined) : {};
|
|
1075
1191
|
promise = promise.then(adapterPayload => {
|
|
1076
1192
|
if (adapterPayload) {
|
|
1077
1193
|
return normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation);
|
|
@@ -1079,4 +1195,13 @@ function _flushPendingSave(store, pending) {
|
|
|
1079
1195
|
});
|
|
1080
1196
|
resolver.resolve(promise);
|
|
1081
1197
|
}
|
|
1082
|
-
|
|
1198
|
+
|
|
1199
|
+
/**
|
|
1200
|
+
* Utilities - often temporary - for maintaining backwards compatibility with
|
|
1201
|
+
* older parts of EmberData.
|
|
1202
|
+
*
|
|
1203
|
+
@module @ember-data/legacy-compat
|
|
1204
|
+
@main @ember-data/legacy-compat
|
|
1205
|
+
*/
|
|
1206
|
+
function upgradeStore(store) {}
|
|
1207
|
+
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 };
|