@ember-data/legacy-compat 5.5.0-alpha.2 → 5.5.0-alpha.21
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-0744e8e9.js → dist/-private-Dlia0pw1.js} +252 -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 +58 -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-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
- /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
|
|
|
@@ -333,7 +344,13 @@ class Snapshot {
|
|
|
333
344
|
@public
|
|
334
345
|
*/
|
|
335
346
|
get record() {
|
|
336
|
-
|
|
347
|
+
const record = this._store.peekRecord(this.identifier);
|
|
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) : {};
|
|
353
|
+
return record;
|
|
337
354
|
}
|
|
338
355
|
get _attributes() {
|
|
339
356
|
if (this.__attributes !== null) {
|
|
@@ -343,10 +360,12 @@ class Snapshot {
|
|
|
343
360
|
const {
|
|
344
361
|
identifier
|
|
345
362
|
} = this;
|
|
346
|
-
const attrs =
|
|
363
|
+
const attrs = this._store.schema.fields(identifier);
|
|
347
364
|
const cache = this._store.cache;
|
|
348
|
-
attrs.forEach(keyName => {
|
|
349
|
-
|
|
365
|
+
attrs.forEach((field, keyName) => {
|
|
366
|
+
if (field.kind === 'attribute') {
|
|
367
|
+
attributes[keyName] = cache.getAttr(identifier, keyName);
|
|
368
|
+
}
|
|
350
369
|
});
|
|
351
370
|
return attributes;
|
|
352
371
|
}
|
|
@@ -373,7 +392,11 @@ class Snapshot {
|
|
|
373
392
|
if (keyName in this._attributes) {
|
|
374
393
|
return this._attributes[keyName];
|
|
375
394
|
}
|
|
376
|
-
|
|
395
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
396
|
+
{
|
|
397
|
+
throw new Error(`Model '${this.identifier.lid}' has no attribute named '${keyName}' defined.`);
|
|
398
|
+
}
|
|
399
|
+
})() : {};
|
|
377
400
|
}
|
|
378
401
|
|
|
379
402
|
/**
|
|
@@ -406,13 +429,13 @@ class Snapshot {
|
|
|
406
429
|
@public
|
|
407
430
|
*/
|
|
408
431
|
changedAttributes() {
|
|
409
|
-
|
|
432
|
+
const changedAttributes = Object.create(null);
|
|
410
433
|
if (!this._changedAttributes) {
|
|
411
434
|
return changedAttributes;
|
|
412
435
|
}
|
|
413
|
-
|
|
436
|
+
const changedAttributeKeys = Object.keys(this._changedAttributes);
|
|
414
437
|
for (let i = 0, length = changedAttributeKeys.length; i < length; i++) {
|
|
415
|
-
|
|
438
|
+
const key = changedAttributeKeys[i];
|
|
416
439
|
changedAttributes[key] = this._changedAttributes[key].slice();
|
|
417
440
|
}
|
|
418
441
|
return changedAttributes;
|
|
@@ -447,40 +470,48 @@ class Snapshot {
|
|
|
447
470
|
will be returned if the contents of the relationship is unknown.
|
|
448
471
|
*/
|
|
449
472
|
belongsTo(keyName, options) {
|
|
450
|
-
|
|
473
|
+
const returnModeIsId = !!(options && options.id);
|
|
451
474
|
let result;
|
|
452
|
-
|
|
475
|
+
const store = this._store;
|
|
453
476
|
if (returnModeIsId === true && keyName in this._belongsToIds) {
|
|
454
477
|
return this._belongsToIds[keyName];
|
|
455
478
|
}
|
|
456
479
|
if (returnModeIsId === false && keyName in this._belongsToRelationships) {
|
|
457
480
|
return this._belongsToRelationships[keyName];
|
|
458
481
|
}
|
|
459
|
-
|
|
482
|
+
const relationshipMeta = store.schema.fields({
|
|
460
483
|
type: this.modelName
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
}
|
|
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', '*')) : {};
|
|
472
495
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
473
496
|
const {
|
|
474
497
|
identifier
|
|
475
498
|
} = this;
|
|
476
|
-
if (macroCondition(
|
|
499
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
477
500
|
const relationship = graphFor(this._store).get(identifier, keyName);
|
|
478
|
-
|
|
479
|
-
|
|
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') : {};
|
|
480
511
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
512
|
+
const value = graphFor(this._store).getData(identifier, keyName);
|
|
513
|
+
const data = value && value.data;
|
|
514
|
+
const inverseIdentifier = data ? store.identifierCache.getOrCreateRecordIdentifier(data) : null;
|
|
484
515
|
if (value && value.data !== undefined) {
|
|
485
516
|
const cache = store.cache;
|
|
486
517
|
if (inverseIdentifier && !cache.isDeleted(inverseIdentifier)) {
|
|
@@ -525,44 +556,58 @@ class Snapshot {
|
|
|
525
556
|
undefined will be returned if the contents of the relationship is unknown.
|
|
526
557
|
*/
|
|
527
558
|
hasMany(keyName, options) {
|
|
528
|
-
|
|
559
|
+
const returnModeIsIds = !!(options && options.ids);
|
|
529
560
|
let results;
|
|
530
|
-
|
|
531
|
-
|
|
561
|
+
const cachedIds = this._hasManyIds[keyName];
|
|
562
|
+
const cachedSnapshots = this._hasManyRelationships[keyName];
|
|
532
563
|
if (returnModeIsIds === true && keyName in this._hasManyIds) {
|
|
533
564
|
return cachedIds;
|
|
534
565
|
}
|
|
535
566
|
if (returnModeIsIds === false && keyName in this._hasManyRelationships) {
|
|
536
567
|
return cachedSnapshots;
|
|
537
568
|
}
|
|
538
|
-
|
|
539
|
-
|
|
569
|
+
const store = this._store;
|
|
570
|
+
const relationshipMeta = store.schema.fields({
|
|
540
571
|
type: this.modelName
|
|
541
|
-
})
|
|
542
|
-
|
|
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') : {};
|
|
543
578
|
|
|
544
579
|
// TODO @runspired it seems this code branch would not work with CUSTOM_MODEL_CLASSes
|
|
545
580
|
// this check is not a regression in behavior because relationships don't currently
|
|
546
581
|
// function without access to intimate API contracts between RecordData and Model.
|
|
547
582
|
// This is a requirement we should fix as soon as the relationship layer does not require
|
|
548
583
|
// this intimate API usage.
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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', '*')) : {};
|
|
552
589
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
553
590
|
const {
|
|
554
591
|
identifier
|
|
555
592
|
} = this;
|
|
556
|
-
if (macroCondition(
|
|
593
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
557
594
|
const relationship = graphFor(this._store).get(identifier, keyName);
|
|
558
|
-
|
|
559
|
-
|
|
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') : {};
|
|
560
605
|
}
|
|
561
|
-
|
|
606
|
+
const value = graphFor(this._store).getData(identifier, keyName);
|
|
562
607
|
if (value.data) {
|
|
563
608
|
results = [];
|
|
564
609
|
value.data.forEach(member => {
|
|
565
|
-
|
|
610
|
+
const inverseIdentifier = store.identifierCache.getOrCreateRecordIdentifier(member);
|
|
566
611
|
const cache = store.cache;
|
|
567
612
|
if (!cache.isDeleted(inverseIdentifier)) {
|
|
568
613
|
if (returnModeIsIds) {
|
|
@@ -599,9 +644,11 @@ class Snapshot {
|
|
|
599
644
|
@public
|
|
600
645
|
*/
|
|
601
646
|
eachAttribute(callback, binding) {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
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
|
+
}
|
|
605
652
|
});
|
|
606
653
|
}
|
|
607
654
|
|
|
@@ -620,9 +667,11 @@ class Snapshot {
|
|
|
620
667
|
@public
|
|
621
668
|
*/
|
|
622
669
|
eachRelationship(callback, binding) {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
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
|
+
}
|
|
626
675
|
});
|
|
627
676
|
}
|
|
628
677
|
|
|
@@ -648,12 +697,17 @@ class Snapshot {
|
|
|
648
697
|
@public
|
|
649
698
|
*/
|
|
650
699
|
serialize(options) {
|
|
700
|
+
upgradeStore(this._store);
|
|
651
701
|
const serializer = this._store.serializerFor(this.modelName);
|
|
652
|
-
|
|
702
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
703
|
+
if (!test) {
|
|
704
|
+
throw new Error(`Cannot serialize record, no serializer found`);
|
|
705
|
+
}
|
|
706
|
+
})(serializer) : {};
|
|
653
707
|
return serializer.serialize(this, options);
|
|
654
708
|
}
|
|
655
709
|
}
|
|
656
|
-
const SaveOp = Symbol('SaveOp');
|
|
710
|
+
const SaveOp = getOrSetGlobal('SaveOp', Symbol('SaveOp'));
|
|
657
711
|
class FetchManager {
|
|
658
712
|
// fetches pending in the runloop, waiting to be coalesced
|
|
659
713
|
|
|
@@ -675,13 +729,13 @@ class FetchManager {
|
|
|
675
729
|
@internal
|
|
676
730
|
*/
|
|
677
731
|
scheduleSave(identifier, options) {
|
|
678
|
-
|
|
679
|
-
|
|
732
|
+
const resolver = createDeferred();
|
|
733
|
+
const query = {
|
|
680
734
|
op: 'saveRecord',
|
|
681
735
|
recordIdentifier: identifier,
|
|
682
736
|
options
|
|
683
737
|
};
|
|
684
|
-
|
|
738
|
+
const queryRequest = {
|
|
685
739
|
data: [query]
|
|
686
740
|
};
|
|
687
741
|
const snapshot = this.createSnapshot(identifier, options);
|
|
@@ -697,19 +751,19 @@ class FetchManager {
|
|
|
697
751
|
return monitored;
|
|
698
752
|
}
|
|
699
753
|
scheduleFetch(identifier, options, request) {
|
|
700
|
-
|
|
754
|
+
const query = {
|
|
701
755
|
op: 'findRecord',
|
|
702
756
|
recordIdentifier: identifier,
|
|
703
757
|
options
|
|
704
758
|
};
|
|
705
|
-
|
|
759
|
+
const queryRequest = {
|
|
706
760
|
data: [query]
|
|
707
761
|
};
|
|
708
|
-
|
|
762
|
+
const pendingFetch = this.getPendingFetch(identifier, options);
|
|
709
763
|
if (pendingFetch) {
|
|
710
764
|
return pendingFetch;
|
|
711
765
|
}
|
|
712
|
-
|
|
766
|
+
const modelName = identifier.type;
|
|
713
767
|
const resolver = createDeferred();
|
|
714
768
|
const pendingFetchItem = {
|
|
715
769
|
identifier,
|
|
@@ -717,7 +771,7 @@ class FetchManager {
|
|
|
717
771
|
options,
|
|
718
772
|
queryRequest
|
|
719
773
|
};
|
|
720
|
-
|
|
774
|
+
const resolverPromise = resolver.promise;
|
|
721
775
|
const store = this._store;
|
|
722
776
|
const isInitialLoad = !store._instanceCache.recordIsLoaded(identifier); // we don't use isLoading directly because we are the request
|
|
723
777
|
|
|
@@ -730,17 +784,21 @@ class FetchManager {
|
|
|
730
784
|
|
|
731
785
|
// additional data received in the payload
|
|
732
786
|
// may result in the merging of identifiers (and thus records)
|
|
733
|
-
|
|
787
|
+
const potentiallyNewIm = store._push(payload, options.reload);
|
|
734
788
|
if (potentiallyNewIm && !Array.isArray(potentiallyNewIm)) {
|
|
735
789
|
return potentiallyNewIm;
|
|
736
790
|
}
|
|
737
791
|
return identifier;
|
|
738
792
|
}, error => {
|
|
739
|
-
|
|
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) : {};
|
|
740
798
|
const cache = store.cache;
|
|
741
799
|
if (!cache || cache.isEmpty(identifier) || isInitialLoad) {
|
|
742
800
|
let isReleasable = true;
|
|
743
|
-
if (macroCondition(
|
|
801
|
+
if (macroCondition(dependencySatisfies('@ember-data/graph', '*'))) {
|
|
744
802
|
if (!cache) {
|
|
745
803
|
const graphFor = importSync('@ember-data/graph/-private').graphFor;
|
|
746
804
|
const graph = graphFor(store);
|
|
@@ -763,7 +821,7 @@ class FetchManager {
|
|
|
763
821
|
this.flushAllPendingFetches();
|
|
764
822
|
});
|
|
765
823
|
}
|
|
766
|
-
|
|
824
|
+
const fetchesByType = this._pendingFetch;
|
|
767
825
|
let fetchesById = fetchesByType.get(modelName);
|
|
768
826
|
if (!fetchesById) {
|
|
769
827
|
fetchesById = new Map();
|
|
@@ -775,7 +833,7 @@ class FetchManager {
|
|
|
775
833
|
fetchesById.set(identifier, requestsForIdentifier);
|
|
776
834
|
}
|
|
777
835
|
requestsForIdentifier.push(pendingFetchItem);
|
|
778
|
-
if (macroCondition(
|
|
836
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.TESTING)) {
|
|
779
837
|
if (!request.disableTestWaiter) {
|
|
780
838
|
const {
|
|
781
839
|
waitForPromise
|
|
@@ -787,11 +845,11 @@ class FetchManager {
|
|
|
787
845
|
return promise;
|
|
788
846
|
}
|
|
789
847
|
getPendingFetch(identifier, options) {
|
|
790
|
-
|
|
848
|
+
const pendingFetches = this._pendingFetch.get(identifier.type)?.get(identifier);
|
|
791
849
|
|
|
792
850
|
// We already have a pending fetch for this
|
|
793
851
|
if (pendingFetches) {
|
|
794
|
-
|
|
852
|
+
const matchingPendingFetch = pendingFetches.find(fetch => isSameRequest(options, fetch.options));
|
|
795
853
|
if (matchingPendingFetch) {
|
|
796
854
|
return matchingPendingFetch.promise;
|
|
797
855
|
}
|
|
@@ -812,7 +870,7 @@ class FetchManager {
|
|
|
812
870
|
let promise;
|
|
813
871
|
if (isEmpty) {
|
|
814
872
|
assertIdentifierHasId(identifier);
|
|
815
|
-
if (macroCondition(
|
|
873
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
816
874
|
promise = this.scheduleFetch(identifier, Object.assign({}, options, {
|
|
817
875
|
reload: true
|
|
818
876
|
}), request);
|
|
@@ -822,7 +880,11 @@ class FetchManager {
|
|
|
822
880
|
}
|
|
823
881
|
} else if (isLoading) {
|
|
824
882
|
promise = this.getPendingFetch(identifier, options);
|
|
825
|
-
|
|
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) : {};
|
|
826
888
|
} else {
|
|
827
889
|
promise = Promise.resolve(identifier);
|
|
828
890
|
}
|
|
@@ -887,27 +949,43 @@ function isSameRequest(options = {}, existingOptions = {}) {
|
|
|
887
949
|
return optionsSatisfies(options.adapterOptions, existingOptions.adapterOptions) && includesSatisfies(options.include, existingOptions.include);
|
|
888
950
|
}
|
|
889
951
|
function _findMany(store, adapter, modelName, snapshots) {
|
|
890
|
-
|
|
891
|
-
|
|
952
|
+
const modelClass = store.modelFor(modelName); // `adapter.findMany` gets the modelClass still
|
|
953
|
+
const promise = Promise.resolve().then(() => {
|
|
892
954
|
const ids = snapshots.map(s => s.id);
|
|
893
|
-
|
|
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)) : {};
|
|
894
960
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
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) : {};
|
|
898
972
|
return ret;
|
|
899
973
|
});
|
|
900
974
|
return promise.then(adapterPayload => {
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
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');
|
|
904
982
|
return payload;
|
|
905
983
|
});
|
|
906
984
|
}
|
|
907
985
|
function rejectFetchedItems(fetchMap, snapshots, error) {
|
|
908
986
|
for (let i = 0, l = snapshots.length; i < l; i++) {
|
|
909
|
-
|
|
910
|
-
|
|
987
|
+
const snapshot = snapshots[i];
|
|
988
|
+
const pair = fetchMap.get(snapshot);
|
|
911
989
|
if (pair) {
|
|
912
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.`));
|
|
913
991
|
}
|
|
@@ -923,9 +1001,9 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
923
1001
|
options object, we resolve all snapshots by id with
|
|
924
1002
|
the first response we see.
|
|
925
1003
|
*/
|
|
926
|
-
|
|
1004
|
+
const snapshotsById = new Map();
|
|
927
1005
|
for (let i = 0; i < snapshots.length; i++) {
|
|
928
|
-
|
|
1006
|
+
const id = snapshots[i].id;
|
|
929
1007
|
let snapshotGroup = snapshotsById.get(id);
|
|
930
1008
|
if (!snapshotGroup) {
|
|
931
1009
|
snapshotGroup = [];
|
|
@@ -936,18 +1014,18 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
936
1014
|
const included = Array.isArray(coalescedPayload.included) ? coalescedPayload.included : [];
|
|
937
1015
|
|
|
938
1016
|
// resolve found records
|
|
939
|
-
|
|
1017
|
+
const resources = coalescedPayload.data;
|
|
940
1018
|
for (let i = 0, l = resources.length; i < l; i++) {
|
|
941
|
-
|
|
942
|
-
|
|
1019
|
+
const resource = resources[i];
|
|
1020
|
+
const snapshotGroup = snapshotsById.get(resource.id);
|
|
943
1021
|
snapshotsById.delete(resource.id);
|
|
944
1022
|
if (!snapshotGroup) {
|
|
945
1023
|
// TODO consider whether this should be a deprecation/assertion
|
|
946
1024
|
included.push(resource);
|
|
947
1025
|
} else {
|
|
948
1026
|
snapshotGroup.forEach(snapshot => {
|
|
949
|
-
|
|
950
|
-
|
|
1027
|
+
const pair = fetchMap.get(snapshot);
|
|
1028
|
+
const resolver = pair.resolver;
|
|
951
1029
|
resolver.resolve({
|
|
952
1030
|
data: resource
|
|
953
1031
|
});
|
|
@@ -965,7 +1043,7 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
965
1043
|
}
|
|
966
1044
|
|
|
967
1045
|
// reject missing records
|
|
968
|
-
|
|
1046
|
+
const rejected = [];
|
|
969
1047
|
snapshotsById.forEach(snapshotArray => {
|
|
970
1048
|
rejected.push(...snapshotArray);
|
|
971
1049
|
});
|
|
@@ -975,23 +1053,47 @@ function handleFoundRecords(store, fetchMap, snapshots, coalescedPayload) {
|
|
|
975
1053
|
rejectFetchedItems(fetchMap, rejected);
|
|
976
1054
|
}
|
|
977
1055
|
function _fetchRecord(store, adapter, fetchItem) {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
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;
|
|
985
1071
|
let promise = Promise.resolve().then(() => {
|
|
986
1072
|
return adapter.findRecord(store, klass, identifier.id, snapshot);
|
|
987
1073
|
});
|
|
988
1074
|
promise = promise.then(adapterPayload => {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
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') : {};
|
|
995
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), {
|
|
996
1098
|
id: 'ds.store.findRecord.id-mismatch'
|
|
997
1099
|
});
|
|
@@ -1009,12 +1111,16 @@ function _processCoalescedGroup(store, fetchMap, group, adapter, modelName) {
|
|
|
1009
1111
|
} else if (group.length === 1) {
|
|
1010
1112
|
_fetchRecord(store, adapter, fetchMap.get(group[0]));
|
|
1011
1113
|
} else {
|
|
1012
|
-
|
|
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
|
+
})() : {};
|
|
1013
1119
|
}
|
|
1014
1120
|
}
|
|
1015
1121
|
function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
1016
|
-
|
|
1017
|
-
|
|
1122
|
+
const adapter = store.adapterFor(modelName);
|
|
1123
|
+
const shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests;
|
|
1018
1124
|
if (shouldCoalesce) {
|
|
1019
1125
|
const pendingFetchItems = [];
|
|
1020
1126
|
pendingFetchMap.forEach((requestsForIdentifier, identifier) => {
|
|
@@ -1026,12 +1132,12 @@ function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
|
1026
1132
|
pendingFetchMap.delete(identifier);
|
|
1027
1133
|
pendingFetchItems.push(requestsForIdentifier[0]);
|
|
1028
1134
|
});
|
|
1029
|
-
|
|
1135
|
+
const totalItems = pendingFetchItems.length;
|
|
1030
1136
|
if (totalItems > 1) {
|
|
1031
|
-
|
|
1032
|
-
|
|
1137
|
+
const snapshots = new Array(totalItems);
|
|
1138
|
+
const fetchMap = new Map();
|
|
1033
1139
|
for (let i = 0; i < totalItems; i++) {
|
|
1034
|
-
|
|
1140
|
+
const fetchItem = pendingFetchItems[i];
|
|
1035
1141
|
snapshots[i] = store._fetchManager.createSnapshot(fetchItem.identifier, fetchItem.options);
|
|
1036
1142
|
fetchMap.set(snapshots[i], fetchItem);
|
|
1037
1143
|
}
|
|
@@ -1045,12 +1151,12 @@ function _flushPendingFetchForType(store, pendingFetchMap, modelName) {
|
|
|
1045
1151
|
_processCoalescedGroup(store, fetchMap, groups[i], adapter, modelName);
|
|
1046
1152
|
}
|
|
1047
1153
|
} else if (totalItems === 1) {
|
|
1048
|
-
|
|
1154
|
+
_fetchRecord(store, adapter, pendingFetchItems[0]);
|
|
1049
1155
|
}
|
|
1050
1156
|
}
|
|
1051
1157
|
pendingFetchMap.forEach(pendingFetchItems => {
|
|
1052
1158
|
pendingFetchItems.forEach(pendingFetchItem => {
|
|
1053
|
-
|
|
1159
|
+
_fetchRecord(store, adapter, pendingFetchItem);
|
|
1054
1160
|
});
|
|
1055
1161
|
});
|
|
1056
1162
|
}
|
|
@@ -1063,13 +1169,25 @@ function _flushPendingSave(store, pending) {
|
|
|
1063
1169
|
} = pending;
|
|
1064
1170
|
const adapter = store.adapterFor(identifier.type);
|
|
1065
1171
|
const operation = options[SaveOp];
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
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') : {};
|
|
1070
1184
|
let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot));
|
|
1071
|
-
|
|
1072
|
-
|
|
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) : {};
|
|
1073
1191
|
promise = promise.then(adapterPayload => {
|
|
1074
1192
|
if (adapterPayload) {
|
|
1075
1193
|
return normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation);
|
|
@@ -1077,4 +1195,13 @@ function _flushPendingSave(store, pending) {
|
|
|
1077
1195
|
});
|
|
1078
1196
|
resolver.resolve(promise);
|
|
1079
1197
|
}
|
|
1080
|
-
|
|
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 };
|