@ember-data/store 5.3.11 → 5.3.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 +2 -2
- package/dist/-private.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{handler-DX830Swd.js → many-array-BwVo-2vv.js} +1397 -544
- package/dist/many-array-BwVo-2vv.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 +26 -45
- package/unstable-preview-types/-private/cache-handler/handler.d.ts.map +1 -1
- package/unstable-preview-types/-private/cache-handler/utils.d.ts +0 -5
- package/unstable-preview-types/-private/cache-handler/utils.d.ts.map +1 -1
- package/unstable-preview-types/-private/caches/identifier-cache.d.ts +7 -3
- package/unstable-preview-types/-private/caches/identifier-cache.d.ts.map +1 -1
- package/unstable-preview-types/-private/caches/instance-cache.d.ts +4 -1
- package/unstable-preview-types/-private/caches/instance-cache.d.ts.map +1 -1
- package/unstable-preview-types/-private/debug/utils.d.ts +9 -0
- package/unstable-preview-types/-private/debug/utils.d.ts.map +1 -0
- package/unstable-preview-types/-private/document.d.ts +23 -14
- package/unstable-preview-types/-private/document.d.ts.map +1 -1
- package/unstable-preview-types/-private/legacy-model-support/shim-model-class.d.ts +3 -3
- package/unstable-preview-types/-private/legacy-model-support/shim-model-class.d.ts.map +1 -1
- package/unstable-preview-types/-private/managers/cache-capabilities-manager.d.ts +3 -3
- package/unstable-preview-types/-private/managers/cache-capabilities-manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/managers/cache-manager.d.ts +22 -0
- package/unstable-preview-types/-private/managers/cache-manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/managers/notification-manager.d.ts +4 -4
- package/unstable-preview-types/-private/managers/notification-manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/managers/record-array-manager.d.ts +9 -5
- package/unstable-preview-types/-private/managers/record-array-manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/record-arrays/identifier-array.d.ts +14 -2
- package/unstable-preview-types/-private/record-arrays/identifier-array.d.ts.map +1 -1
- package/unstable-preview-types/-private/record-arrays/many-array.d.ts +199 -0
- package/unstable-preview-types/-private/record-arrays/many-array.d.ts.map +1 -0
- package/unstable-preview-types/-private/store-service.d.ts +62 -6
- package/unstable-preview-types/-private/store-service.d.ts.map +1 -1
- package/unstable-preview-types/-private.d.ts +4 -2
- package/unstable-preview-types/-private.d.ts.map +1 -1
- package/unstable-preview-types/-types/q/cache-capabilities-manager.d.ts +4 -4
- package/unstable-preview-types/-types/q/cache-capabilities-manager.d.ts.map +1 -1
- package/unstable-preview-types/-types/q/ds-model.d.ts +3 -3
- package/unstable-preview-types/-types/q/ds-model.d.ts.map +1 -1
- package/unstable-preview-types/-types/q/schema-service.d.ts +13 -5
- package/unstable-preview-types/-types/q/schema-service.d.ts.map +1 -1
- package/unstable-preview-types/index.d.ts +22 -20
- package/dist/handler-DX830Swd.js.map +0 -1
- /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,11 +1,12 @@
|
|
|
1
1
|
import { deprecate, warn } from '@ember/debug';
|
|
2
2
|
import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
|
|
3
3
|
import { EnableHydration, SkipCache } from '@warp-drive/core-types/request';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { dasherize } from '@ember-data/request-utils/string';
|
|
7
|
-
import { defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
|
|
4
|
+
import { setLogging, getRuntimeConfig } from '@warp-drive/core-types/runtime';
|
|
5
|
+
import { getOrSetGlobal, peekTransient, setTransient } from '@warp-drive/core-types/-private';
|
|
8
6
|
import { _backburner } from '@ember/runloop';
|
|
7
|
+
import { defineSubscription, notifySignal, defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
|
|
8
|
+
import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_IDENTIFIER_BUCKET, DEBUG_CLIENT_ORIGINATED } from '@warp-drive/core-types/identifier';
|
|
9
|
+
import { dasherize } from '@ember-data/request-utils/string';
|
|
9
10
|
import { compat } from '@ember-data/tracking';
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -129,10 +130,9 @@ function hasType(resource) {
|
|
|
129
130
|
/**
|
|
130
131
|
@module @ember-data/store
|
|
131
132
|
*/
|
|
132
|
-
const IDENTIFIERS = getOrSetGlobal('IDENTIFIERS', new Set());
|
|
133
133
|
const DOCUMENTS = getOrSetGlobal('DOCUMENTS', new Set());
|
|
134
134
|
function isStableIdentifier(identifier) {
|
|
135
|
-
return identifier[CACHE_OWNER] !== undefined
|
|
135
|
+
return identifier[CACHE_OWNER] !== undefined;
|
|
136
136
|
}
|
|
137
137
|
function isDocumentIdentifier(identifier) {
|
|
138
138
|
return DOCUMENTS.has(identifier);
|
|
@@ -310,9 +310,11 @@ class IdentifierCache {
|
|
|
310
310
|
*/
|
|
311
311
|
|
|
312
312
|
_getRecordIdentifier(resource, shouldGenerate) {
|
|
313
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
314
|
-
|
|
315
|
-
|
|
313
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
314
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
315
|
+
// eslint-disable-next-line no-console
|
|
316
|
+
console.groupCollapsed(`Identifiers: ${shouldGenerate ? 'Generating' : 'Peeking'} Identifier`, resource);
|
|
317
|
+
}
|
|
316
318
|
}
|
|
317
319
|
// short circuit if we're already the stable version
|
|
318
320
|
if (isStableIdentifier(resource)) {
|
|
@@ -322,33 +324,41 @@ class IdentifierCache {
|
|
|
322
324
|
throw new Error(`The supplied identifier ${JSON.stringify(resource)} does not belong to this store instance`);
|
|
323
325
|
}
|
|
324
326
|
}
|
|
325
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
327
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
328
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
329
|
+
// eslint-disable-next-line no-console
|
|
330
|
+
console.log(`Identifiers: cache HIT - Stable ${resource.lid}`);
|
|
331
|
+
// eslint-disable-next-line no-console
|
|
332
|
+
console.groupEnd();
|
|
333
|
+
}
|
|
330
334
|
}
|
|
331
335
|
return resource;
|
|
332
336
|
}
|
|
333
337
|
|
|
334
338
|
// the resource is unknown, ask the application to identify this data for us
|
|
335
339
|
const lid = this._generate(resource, 'record');
|
|
336
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
337
|
-
|
|
338
|
-
|
|
340
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
341
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
342
|
+
// eslint-disable-next-line no-console
|
|
343
|
+
console.log(`Identifiers: ${lid ? 'no ' : ''}lid ${lid ? lid + ' ' : ''}determined for resource`, resource);
|
|
344
|
+
}
|
|
339
345
|
}
|
|
340
346
|
let identifier = /*#__NOINLINE__*/getIdentifierFromLid(this._cache, lid, resource);
|
|
341
347
|
if (identifier !== null) {
|
|
342
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
343
|
-
|
|
344
|
-
|
|
348
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
349
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
350
|
+
// eslint-disable-next-line no-console
|
|
351
|
+
console.groupEnd();
|
|
352
|
+
}
|
|
345
353
|
}
|
|
346
354
|
return identifier;
|
|
347
355
|
}
|
|
348
356
|
if (shouldGenerate === 0) {
|
|
349
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
350
|
-
|
|
351
|
-
|
|
357
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
358
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
359
|
+
// eslint-disable-next-line no-console
|
|
360
|
+
console.groupEnd();
|
|
361
|
+
}
|
|
352
362
|
}
|
|
353
363
|
return;
|
|
354
364
|
}
|
|
@@ -366,9 +376,11 @@ class IdentifierCache {
|
|
|
366
376
|
identifier = /*#__NOINLINE__*/makeStableRecordIdentifier(keyInfo, 'record', false);
|
|
367
377
|
}
|
|
368
378
|
addResourceToCache(this._cache, identifier);
|
|
369
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
370
|
-
|
|
371
|
-
|
|
379
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
380
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
381
|
+
// eslint-disable-next-line no-console
|
|
382
|
+
console.groupEnd();
|
|
383
|
+
}
|
|
372
384
|
}
|
|
373
385
|
return identifier;
|
|
374
386
|
}
|
|
@@ -462,9 +474,11 @@ class IdentifierCache {
|
|
|
462
474
|
|
|
463
475
|
/*#__NOINLINE__*/
|
|
464
476
|
addResourceToCache(this._cache, identifier);
|
|
465
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
466
|
-
|
|
467
|
-
|
|
477
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
478
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
479
|
+
// eslint-disable-next-line no-console
|
|
480
|
+
console.log(`Identifiers: created identifier ${String(identifier)} for newly generated resource`, data);
|
|
481
|
+
}
|
|
468
482
|
}
|
|
469
483
|
return identifier;
|
|
470
484
|
}
|
|
@@ -511,9 +525,11 @@ class IdentifierCache {
|
|
|
511
525
|
if (hadLid) {
|
|
512
526
|
data.lid = identifier.lid;
|
|
513
527
|
}
|
|
514
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
515
|
-
|
|
516
|
-
|
|
528
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
529
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
530
|
+
// eslint-disable-next-line no-console
|
|
531
|
+
console.log(`Identifiers: merged identifiers ${generatedIdentifier.lid} and ${existingIdentifier.lid} for resource into ${identifier.lid}`, data);
|
|
532
|
+
}
|
|
517
533
|
}
|
|
518
534
|
}
|
|
519
535
|
const id = identifier.id;
|
|
@@ -523,9 +539,11 @@ class IdentifierCache {
|
|
|
523
539
|
|
|
524
540
|
// add to our own secondary lookup table
|
|
525
541
|
if (id !== newId && newId !== null) {
|
|
526
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
527
|
-
|
|
528
|
-
|
|
542
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
543
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
544
|
+
// eslint-disable-next-line no-console
|
|
545
|
+
console.log(`Identifiers: updated id for identifier ${identifier.lid} from '${String(id)}' to '${String(newId)}' for resource`, data);
|
|
546
|
+
}
|
|
529
547
|
}
|
|
530
548
|
const typeSet = this._cache.resourcesByType[identifier.type];
|
|
531
549
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
@@ -537,9 +555,11 @@ class IdentifierCache {
|
|
|
537
555
|
if (id !== null) {
|
|
538
556
|
typeSet.id.delete(id);
|
|
539
557
|
}
|
|
540
|
-
} else if (macroCondition(getGlobalConfig().WarpDrive.
|
|
541
|
-
|
|
542
|
-
|
|
558
|
+
} else if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
559
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
560
|
+
// eslint-disable-next-line no-console
|
|
561
|
+
console.log(`Identifiers: updated identifier ${identifier.lid} resource`, data);
|
|
562
|
+
}
|
|
543
563
|
}
|
|
544
564
|
return identifier;
|
|
545
565
|
}
|
|
@@ -621,11 +641,12 @@ class IdentifierCache {
|
|
|
621
641
|
identifier[DEBUG_STALE_CACHE_OWNER] = identifier[CACHE_OWNER];
|
|
622
642
|
}
|
|
623
643
|
identifier[CACHE_OWNER] = undefined;
|
|
624
|
-
IDENTIFIERS.delete(identifier);
|
|
625
644
|
this._forget(identifier, 'record');
|
|
626
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
627
|
-
|
|
628
|
-
|
|
645
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
646
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
647
|
+
// eslint-disable-next-line no-console
|
|
648
|
+
console.log(`Identifiers: released identifier ${identifierObject.lid}`);
|
|
649
|
+
}
|
|
629
650
|
}
|
|
630
651
|
}
|
|
631
652
|
destroy() {
|
|
@@ -637,20 +658,17 @@ class IdentifierCache {
|
|
|
637
658
|
}
|
|
638
659
|
}
|
|
639
660
|
function makeStableRecordIdentifier(recordIdentifier, bucket, clientOriginated) {
|
|
640
|
-
IDENTIFIERS.add(recordIdentifier);
|
|
641
661
|
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
642
662
|
// we enforce immutability in dev
|
|
643
663
|
// but preserve our ability to do controlled updates to the reference
|
|
644
664
|
let wrapper = {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
},
|
|
665
|
+
type: recordIdentifier.type,
|
|
666
|
+
lid: recordIdentifier.lid,
|
|
648
667
|
get id() {
|
|
649
668
|
return recordIdentifier.id;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
},
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
const proto = {
|
|
654
672
|
get [CACHE_OWNER]() {
|
|
655
673
|
return recordIdentifier[CACHE_OWNER];
|
|
656
674
|
},
|
|
@@ -662,9 +680,15 @@ function makeStableRecordIdentifier(recordIdentifier, bucket, clientOriginated)
|
|
|
662
680
|
},
|
|
663
681
|
set [DEBUG_STALE_CACHE_OWNER](value) {
|
|
664
682
|
recordIdentifier[DEBUG_STALE_CACHE_OWNER] = value;
|
|
683
|
+
},
|
|
684
|
+
get [DEBUG_CLIENT_ORIGINATED]() {
|
|
685
|
+
return clientOriginated;
|
|
686
|
+
},
|
|
687
|
+
get [DEBUG_IDENTIFIER_BUCKET]() {
|
|
688
|
+
return bucket;
|
|
665
689
|
}
|
|
666
690
|
};
|
|
667
|
-
Object.defineProperty(
|
|
691
|
+
Object.defineProperty(proto, 'toString', {
|
|
668
692
|
enumerable: false,
|
|
669
693
|
value: () => {
|
|
670
694
|
const {
|
|
@@ -675,7 +699,7 @@ function makeStableRecordIdentifier(recordIdentifier, bucket, clientOriginated)
|
|
|
675
699
|
return `${clientOriginated ? '[CLIENT_ORIGINATED] ' : ''}${String(type)}:${String(id)} (${lid})`;
|
|
676
700
|
}
|
|
677
701
|
});
|
|
678
|
-
Object.defineProperty(
|
|
702
|
+
Object.defineProperty(proto, 'toJSON', {
|
|
679
703
|
enumerable: false,
|
|
680
704
|
value: () => {
|
|
681
705
|
const {
|
|
@@ -690,9 +714,7 @@ function makeStableRecordIdentifier(recordIdentifier, bucket, clientOriginated)
|
|
|
690
714
|
};
|
|
691
715
|
}
|
|
692
716
|
});
|
|
693
|
-
wrapper
|
|
694
|
-
wrapper[DEBUG_IDENTIFIER_BUCKET] = bucket;
|
|
695
|
-
IDENTIFIERS.add(wrapper);
|
|
717
|
+
Object.setPrototypeOf(wrapper, proto);
|
|
696
718
|
DEBUG_MAP.set(wrapper, recordIdentifier);
|
|
697
719
|
wrapper = freeze(wrapper);
|
|
698
720
|
return wrapper;
|
|
@@ -775,9 +797,11 @@ function detectMerge(cache, keyInfo, identifier, data) {
|
|
|
775
797
|
}
|
|
776
798
|
function getIdentifierFromLid(cache, lid, resource) {
|
|
777
799
|
const identifier = cache.resources.get(lid);
|
|
778
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
779
|
-
|
|
780
|
-
|
|
800
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
801
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
802
|
+
// eslint-disable-next-line no-console
|
|
803
|
+
console.log(`Identifiers: cache ${identifier ? 'HIT' : 'MISS'} - Non-Stable ${lid}`, resource);
|
|
804
|
+
}
|
|
781
805
|
}
|
|
782
806
|
return identifier || null;
|
|
783
807
|
}
|
|
@@ -796,77 +820,461 @@ function addResourceToCache(cache, identifier) {
|
|
|
796
820
|
typeSet.id.set(identifier.id, identifier);
|
|
797
821
|
}
|
|
798
822
|
}
|
|
823
|
+
const TEXT_COLORS = {
|
|
824
|
+
TEXT: 'inherit',
|
|
825
|
+
notify: ['white', 'white', 'inherit', 'magenta', 'inherit'],
|
|
826
|
+
'reactive-ui': ['white', 'white', 'inherit', 'magenta', 'inherit'],
|
|
827
|
+
graph: ['white', 'white', 'inherit', 'magenta', 'inherit'],
|
|
828
|
+
request: ['white', 'white', 'inherit', 'magenta', 'inherit'],
|
|
829
|
+
cache: ['white', 'white', 'inherit', 'magenta', 'inherit']
|
|
830
|
+
};
|
|
831
|
+
const BG_COLORS = {
|
|
832
|
+
TEXT: 'transparent',
|
|
833
|
+
notify: ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent'],
|
|
834
|
+
'reactive-ui': ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent'],
|
|
835
|
+
graph: ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent'],
|
|
836
|
+
request: ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent'],
|
|
837
|
+
cache: ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent']
|
|
838
|
+
};
|
|
839
|
+
const NOTIFY_BORDER = {
|
|
840
|
+
TEXT: 0,
|
|
841
|
+
notify: [3, 2, 0, 0, 0],
|
|
842
|
+
'reactive-ui': [3, 2, 0, 0, 0],
|
|
843
|
+
graph: [3, 2, 0, 0, 0],
|
|
844
|
+
request: [3, 2, 0, 0, 0],
|
|
845
|
+
cache: [3, 2, 0, 0, 0]
|
|
846
|
+
};
|
|
847
|
+
const LIGHT_DARK_ALT = {
|
|
848
|
+
lightgreen: 'green',
|
|
849
|
+
green: 'lightgreen'
|
|
850
|
+
};
|
|
851
|
+
function badge(isLight, color, bgColor, border) {
|
|
852
|
+
return [`color: ${correctColor(isLight, color)}; background-color: ${correctColor(isLight, bgColor)}; padding: ${border}px ${2 * border}px; border-radius: ${border}px;`, `color: ${TEXT_COLORS.TEXT}; background-color: ${BG_COLORS.TEXT};`];
|
|
853
|
+
}
|
|
854
|
+
function colorForBucket(isLight, scope, bucket) {
|
|
855
|
+
if (scope === 'notify') {
|
|
856
|
+
return bucket === 'added' ? badge(isLight, 'lightgreen', 'transparent', 0) : bucket === 'removed' ? badge(isLight, 'red', 'transparent', 0) : badge(isLight, TEXT_COLORS[scope][2], BG_COLORS[scope][2], NOTIFY_BORDER[scope][2]);
|
|
857
|
+
}
|
|
858
|
+
if (scope === 'reactive-ui') {
|
|
859
|
+
return bucket === 'created' ? badge(isLight, 'lightgreen', 'transparent', 0) : bucket === 'disconnected' ? badge(isLight, 'red', 'transparent', 0) : badge(isLight, TEXT_COLORS[scope][2], BG_COLORS[scope][2], NOTIFY_BORDER[scope][2]);
|
|
860
|
+
}
|
|
861
|
+
if (scope === 'cache') {
|
|
862
|
+
return bucket === 'inserted' ? badge(isLight, 'lightgreen', 'transparent', 0) : bucket === 'removed' ? badge(isLight, 'red', 'transparent', 0) : badge(isLight, TEXT_COLORS[scope][2], BG_COLORS[scope][2], NOTIFY_BORDER[scope][2]);
|
|
863
|
+
}
|
|
864
|
+
return badge(isLight, TEXT_COLORS[scope][3], BG_COLORS[scope][3], NOTIFY_BORDER[scope][3]);
|
|
865
|
+
}
|
|
866
|
+
function logGroup(scope, prefix, subScop1, subScop2, subScop3, subScop4) {
|
|
867
|
+
// eslint-disable-next-line no-console
|
|
868
|
+
console.groupCollapsed(..._log(scope, prefix, subScop1, subScop2, subScop3, subScop4));
|
|
869
|
+
}
|
|
870
|
+
function log(scope, prefix, subScop1, subScop2, subScop3, subScop4) {
|
|
871
|
+
// eslint-disable-next-line no-console
|
|
872
|
+
console.log(..._log(scope, prefix, subScop1, subScop2, subScop3, subScop4));
|
|
873
|
+
}
|
|
874
|
+
function correctColor(isLight, color) {
|
|
875
|
+
if (!isLight) {
|
|
876
|
+
return color;
|
|
877
|
+
}
|
|
878
|
+
return color in LIGHT_DARK_ALT ? LIGHT_DARK_ALT[color] : color;
|
|
879
|
+
}
|
|
880
|
+
function isLightMode() {
|
|
881
|
+
if (window?.matchMedia?.('(prefers-color-scheme: light)').matches) {
|
|
882
|
+
return true;
|
|
883
|
+
}
|
|
884
|
+
return false;
|
|
885
|
+
}
|
|
886
|
+
function _log(scope, prefix, subScop1, subScop2, subScop3, subScop4) {
|
|
887
|
+
const isLight = isLightMode();
|
|
888
|
+
switch (scope) {
|
|
889
|
+
case 'reactive-ui':
|
|
890
|
+
case 'notify':
|
|
891
|
+
{
|
|
892
|
+
const scopePath = prefix ? `[${prefix}] ${scope}` : scope;
|
|
893
|
+
const path = subScop4 ? `${subScop3}.${subScop4}` : subScop3;
|
|
894
|
+
return [`%c@warp%c-%cdrive%c %c${scopePath}%c %c${subScop1}%c %c${subScop2}%c %c${path}%c`, ...badge(isLight, 'lightgreen', 'transparent', 0), ...badge(isLight, 'magenta', 'transparent', 0), ...badge(isLight, TEXT_COLORS[scope][0], BG_COLORS[scope][0], NOTIFY_BORDER[scope][0]), ...badge(isLight, TEXT_COLORS[scope][1], BG_COLORS[scope][1], NOTIFY_BORDER[scope][1]), ...badge(isLight, TEXT_COLORS[scope][2], BG_COLORS[scope][2], NOTIFY_BORDER[scope][2]), ...colorForBucket(isLight, scope, path)];
|
|
895
|
+
}
|
|
896
|
+
case 'cache':
|
|
897
|
+
{
|
|
898
|
+
const scopePath = prefix ? `${scope} (${prefix})` : scope;
|
|
899
|
+
return [`%c@warp%c-%cdrive%c %c${scopePath}%c %c${subScop1}%c %c${subScop2}%c %c${subScop3}%c %c${subScop4}%c`, ...badge(isLight, 'lightgreen', 'transparent', 0), ...badge(isLight, 'magenta', 'transparent', 0), ...badge(isLight, TEXT_COLORS[scope][0], BG_COLORS[scope][0], NOTIFY_BORDER[scope][0]), ...badge(isLight, TEXT_COLORS[scope][1], BG_COLORS[scope][1], NOTIFY_BORDER[scope][1]), ...badge(isLight, TEXT_COLORS[scope][2], BG_COLORS[scope][2], NOTIFY_BORDER[scope][2]), ...colorForBucket(isLight, scope, subScop3), ...badge(isLight, TEXT_COLORS[scope][4], BG_COLORS[scope][4], NOTIFY_BORDER[scope][4])];
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
return [];
|
|
903
|
+
}
|
|
799
904
|
|
|
800
905
|
/**
|
|
801
|
-
|
|
802
|
-
*/
|
|
906
|
+
* @module @ember-data/store
|
|
907
|
+
*/
|
|
908
|
+
function urlFromLink(link) {
|
|
909
|
+
if (typeof link === 'string') return link;
|
|
910
|
+
return link.href;
|
|
911
|
+
}
|
|
803
912
|
|
|
804
913
|
/**
|
|
805
|
-
|
|
806
|
-
|
|
914
|
+
* A Document is a class that wraps the response content from a request to the API
|
|
915
|
+
* returned by `Cache.put` or `Cache.peek`, converting resource-identifiers into
|
|
916
|
+
* record instances.
|
|
917
|
+
*
|
|
918
|
+
* It is not directly instantiated by the user, and its properties should not
|
|
919
|
+
* be directly modified. Whether individual properties are mutable or not is
|
|
920
|
+
* determined by the record instance itself.
|
|
921
|
+
*
|
|
922
|
+
* @public
|
|
923
|
+
* @class ReactiveDocument
|
|
924
|
+
*/
|
|
925
|
+
class ReactiveDocument {
|
|
926
|
+
/**
|
|
927
|
+
* The links object for this document, if any
|
|
928
|
+
*
|
|
929
|
+
* e.g.
|
|
930
|
+
*
|
|
931
|
+
* ```
|
|
932
|
+
* {
|
|
933
|
+
* self: '/articles?page[number]=3',
|
|
934
|
+
* }
|
|
935
|
+
* ```
|
|
936
|
+
*
|
|
937
|
+
* @property links
|
|
938
|
+
* @type {object|undefined} - a links object
|
|
939
|
+
* @public
|
|
940
|
+
*/
|
|
807
941
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
942
|
+
/**
|
|
943
|
+
* The primary data for this document, if any.
|
|
944
|
+
*
|
|
945
|
+
* If this document has no primary data (e.g. because it is an error document)
|
|
946
|
+
* this property will be `undefined`.
|
|
947
|
+
*
|
|
948
|
+
* For collections this will be an array of record instances,
|
|
949
|
+
* for single resource requests it will be a single record instance or null.
|
|
950
|
+
*
|
|
951
|
+
* @property data
|
|
952
|
+
* @public
|
|
953
|
+
* @type {object|Array<object>|null|undefined} - a data object
|
|
954
|
+
*/
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* The errors returned by the API for this request, if any
|
|
958
|
+
*
|
|
959
|
+
* @property errors
|
|
960
|
+
* @public
|
|
961
|
+
* @type {object|undefined} - an errors object
|
|
962
|
+
*/
|
|
963
|
+
|
|
964
|
+
/**
|
|
965
|
+
* The meta object for this document, if any
|
|
966
|
+
*
|
|
967
|
+
* @property meta
|
|
968
|
+
* @public
|
|
969
|
+
* @type {object|undefined} - a meta object
|
|
970
|
+
*/
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* The identifier associated with this document, if any
|
|
974
|
+
*
|
|
975
|
+
* @property identifier
|
|
976
|
+
* @public
|
|
977
|
+
* @type {StableDocumentIdentifier|null}
|
|
978
|
+
*/
|
|
979
|
+
|
|
980
|
+
constructor(store, identifier, localCache) {
|
|
981
|
+
this._store = store;
|
|
982
|
+
this._localCache = localCache;
|
|
983
|
+
this.identifier = identifier;
|
|
984
|
+
|
|
985
|
+
// TODO if we ever enable auto-cleanup of the cache, we will need to tear this down
|
|
986
|
+
// in a destroy method
|
|
987
|
+
if (identifier) {
|
|
988
|
+
store.notifications.subscribe(identifier, (_identifier, type) => {
|
|
989
|
+
switch (type) {
|
|
990
|
+
case 'updated':
|
|
991
|
+
// FIXME in the case of a collection we need to notify it's length
|
|
992
|
+
// and have it recalc
|
|
993
|
+
notifySignal(this, 'data');
|
|
994
|
+
notifySignal(this, 'links');
|
|
995
|
+
notifySignal(this, 'meta');
|
|
996
|
+
notifySignal(this, 'errors');
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
823
1001
|
}
|
|
824
|
-
|
|
825
|
-
this.
|
|
1002
|
+
async #request(link, options) {
|
|
1003
|
+
const href = this.links?.[link];
|
|
1004
|
+
if (!href) {
|
|
1005
|
+
return null;
|
|
1006
|
+
}
|
|
1007
|
+
options.method = options.method || 'GET';
|
|
1008
|
+
Object.assign(options, {
|
|
1009
|
+
url: urlFromLink(href)
|
|
1010
|
+
});
|
|
1011
|
+
const response = await this._store.request(options);
|
|
1012
|
+
return response.content;
|
|
826
1013
|
}
|
|
827
|
-
|
|
828
|
-
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* Fetches the related link for this document, returning a promise that resolves
|
|
1017
|
+
* with the document when the request completes. If no related link is present,
|
|
1018
|
+
* will fallback to the self link if present
|
|
1019
|
+
*
|
|
1020
|
+
* @method fetch
|
|
1021
|
+
* @public
|
|
1022
|
+
* @param {object} options
|
|
1023
|
+
* @return Promise<Document>
|
|
1024
|
+
*/
|
|
1025
|
+
fetch(options = {}) {
|
|
1026
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1027
|
+
if (!test) {
|
|
1028
|
+
throw new Error(`No self or related link`);
|
|
1029
|
+
}
|
|
1030
|
+
})(this.links?.related || this.links?.self) : {};
|
|
1031
|
+
options.cacheOptions = options.cacheOptions || {};
|
|
1032
|
+
options.cacheOptions.key = this.identifier?.lid;
|
|
1033
|
+
return this.#request(this.links.related ? 'related' : 'self', options);
|
|
829
1034
|
}
|
|
830
1035
|
|
|
831
1036
|
/**
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
*/
|
|
844
|
-
id() {
|
|
845
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
846
|
-
this._ref; // consume the tracked prop
|
|
847
|
-
return this.___identifier.id;
|
|
1037
|
+
* Fetches the next link for this document, returning a promise that resolves
|
|
1038
|
+
* with the new document when the request completes, or null if there is no
|
|
1039
|
+
* next link.
|
|
1040
|
+
*
|
|
1041
|
+
* @method next
|
|
1042
|
+
* @public
|
|
1043
|
+
* @param {object} options
|
|
1044
|
+
* @return Promise<Document | null>
|
|
1045
|
+
*/
|
|
1046
|
+
next(options = {}) {
|
|
1047
|
+
return this.#request('next', options);
|
|
848
1048
|
}
|
|
849
1049
|
|
|
850
1050
|
/**
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
*/
|
|
863
|
-
identifier() {
|
|
864
|
-
return this.___identifier;
|
|
1051
|
+
* Fetches the prev link for this document, returning a promise that resolves
|
|
1052
|
+
* with the new document when the request completes, or null if there is no
|
|
1053
|
+
* prev link.
|
|
1054
|
+
*
|
|
1055
|
+
* @method prev
|
|
1056
|
+
* @public
|
|
1057
|
+
* @param {object} options
|
|
1058
|
+
* @return Promise<Document | null>
|
|
1059
|
+
*/
|
|
1060
|
+
prev(options = {}) {
|
|
1061
|
+
return this.#request('prev', options);
|
|
865
1062
|
}
|
|
866
1063
|
|
|
867
1064
|
/**
|
|
868
|
-
|
|
869
|
-
|
|
1065
|
+
* Fetches the first link for this document, returning a promise that resolves
|
|
1066
|
+
* with the new document when the request completes, or null if there is no
|
|
1067
|
+
* first link.
|
|
1068
|
+
*
|
|
1069
|
+
* @method first
|
|
1070
|
+
* @public
|
|
1071
|
+
* @param {object} options
|
|
1072
|
+
* @return Promise<Document | null>
|
|
1073
|
+
*/
|
|
1074
|
+
first(options = {}) {
|
|
1075
|
+
return this.#request('first', options);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
/**
|
|
1079
|
+
* Fetches the last link for this document, returning a promise that resolves
|
|
1080
|
+
* with the new document when the request completes, or null if there is no
|
|
1081
|
+
* last link.
|
|
1082
|
+
*
|
|
1083
|
+
* @method last
|
|
1084
|
+
* @public
|
|
1085
|
+
* @param {object} options
|
|
1086
|
+
* @return Promise<Document | null>
|
|
1087
|
+
*/
|
|
1088
|
+
last(options = {}) {
|
|
1089
|
+
return this.#request('last', options);
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Implemented for `JSON.stringify` support.
|
|
1094
|
+
*
|
|
1095
|
+
* Returns the JSON representation of the document wrapper.
|
|
1096
|
+
*
|
|
1097
|
+
* This is a shallow serialization, it does not deeply serialize
|
|
1098
|
+
* the document's contents, leaving that to the individual record
|
|
1099
|
+
* instances to determine how to do, if at all.
|
|
1100
|
+
*
|
|
1101
|
+
* @method toJSON
|
|
1102
|
+
* @public
|
|
1103
|
+
* @return
|
|
1104
|
+
*/
|
|
1105
|
+
toJSON() {
|
|
1106
|
+
const data = {};
|
|
1107
|
+
data.identifier = this.identifier;
|
|
1108
|
+
if (this.data !== undefined) {
|
|
1109
|
+
data.data = this.data;
|
|
1110
|
+
}
|
|
1111
|
+
if (this.links !== undefined) {
|
|
1112
|
+
data.links = this.links;
|
|
1113
|
+
}
|
|
1114
|
+
if (this.errors !== undefined) {
|
|
1115
|
+
data.errors = this.errors;
|
|
1116
|
+
}
|
|
1117
|
+
if (this.meta !== undefined) {
|
|
1118
|
+
data.meta = this.meta;
|
|
1119
|
+
}
|
|
1120
|
+
return data;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
defineSubscription(ReactiveDocument.prototype, 'errors', {
|
|
1124
|
+
get() {
|
|
1125
|
+
const {
|
|
1126
|
+
identifier
|
|
1127
|
+
} = this;
|
|
1128
|
+
if (!identifier) {
|
|
1129
|
+
const {
|
|
1130
|
+
document
|
|
1131
|
+
} = this._localCache;
|
|
1132
|
+
if ('errors' in document) {
|
|
1133
|
+
return document.errors;
|
|
1134
|
+
}
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
const doc = this._store.cache.peek(identifier);
|
|
1138
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1139
|
+
if (!test) {
|
|
1140
|
+
throw new Error(`No cache data was found for the document '${identifier.lid}'`);
|
|
1141
|
+
}
|
|
1142
|
+
})(doc) : {};
|
|
1143
|
+
return 'errors' in doc ? doc.errors : undefined;
|
|
1144
|
+
}
|
|
1145
|
+
});
|
|
1146
|
+
defineSubscription(ReactiveDocument.prototype, 'data', {
|
|
1147
|
+
get() {
|
|
1148
|
+
const {
|
|
1149
|
+
identifier,
|
|
1150
|
+
_localCache
|
|
1151
|
+
} = this;
|
|
1152
|
+
const doc = identifier ? this._store.cache.peek(identifier) : _localCache.document;
|
|
1153
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1154
|
+
if (!test) {
|
|
1155
|
+
throw new Error(`No cache data was found for the document '${identifier?.lid ?? '<uncached document>'}'`);
|
|
1156
|
+
}
|
|
1157
|
+
})(doc) : {};
|
|
1158
|
+
const data = 'data' in doc ? doc.data : undefined;
|
|
1159
|
+
if (Array.isArray(data)) {
|
|
1160
|
+
return this._store.recordArrayManager.getCollection({
|
|
1161
|
+
type: identifier ? identifier.lid : _localCache.request.url,
|
|
1162
|
+
identifiers: data.slice(),
|
|
1163
|
+
doc: identifier ? undefined : doc,
|
|
1164
|
+
identifier: identifier ?? null
|
|
1165
|
+
});
|
|
1166
|
+
} else if (data) {
|
|
1167
|
+
return this._store.peekRecord(data);
|
|
1168
|
+
} else {
|
|
1169
|
+
return data;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
});
|
|
1173
|
+
defineSubscription(ReactiveDocument.prototype, 'links', {
|
|
1174
|
+
get() {
|
|
1175
|
+
const {
|
|
1176
|
+
identifier
|
|
1177
|
+
} = this;
|
|
1178
|
+
if (!identifier) {
|
|
1179
|
+
return this._localCache.document.links;
|
|
1180
|
+
}
|
|
1181
|
+
const data = this._store.cache.peek(identifier);
|
|
1182
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1183
|
+
if (!test) {
|
|
1184
|
+
throw new Error(`No cache data was found for the document '${identifier.lid}'`);
|
|
1185
|
+
}
|
|
1186
|
+
})(data) : {};
|
|
1187
|
+
return data.links;
|
|
1188
|
+
}
|
|
1189
|
+
});
|
|
1190
|
+
defineSubscription(ReactiveDocument.prototype, 'meta', {
|
|
1191
|
+
get() {
|
|
1192
|
+
const {
|
|
1193
|
+
identifier
|
|
1194
|
+
} = this;
|
|
1195
|
+
if (!identifier) {
|
|
1196
|
+
return this._localCache.document.meta;
|
|
1197
|
+
}
|
|
1198
|
+
const data = this._store.cache.peek(identifier);
|
|
1199
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
1200
|
+
if (!test) {
|
|
1201
|
+
throw new Error(`No cache data was found for the document '${identifier.lid}'`);
|
|
1202
|
+
}
|
|
1203
|
+
})(data) : {};
|
|
1204
|
+
return data.meta;
|
|
1205
|
+
}
|
|
1206
|
+
});
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
@module @ember-data/store
|
|
1210
|
+
*/
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
A `RecordReference` is a low-level API that allows users and
|
|
1214
|
+
addon authors to perform meta-operations on a record.
|
|
1215
|
+
|
|
1216
|
+
@class RecordReference
|
|
1217
|
+
@public
|
|
1218
|
+
*/
|
|
1219
|
+
class RecordReference {
|
|
1220
|
+
// unsubscribe token given to us by the notification manager
|
|
1221
|
+
___token;
|
|
1222
|
+
___identifier;
|
|
1223
|
+
constructor(store, identifier) {
|
|
1224
|
+
this.store = store;
|
|
1225
|
+
this.___identifier = identifier;
|
|
1226
|
+
this.___token = store.notifications.subscribe(identifier, (_, bucket, notifiedKey) => {
|
|
1227
|
+
if (bucket === 'identity' || bucket === 'attributes' && notifiedKey === 'id') {
|
|
1228
|
+
this._ref++;
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
destroy() {
|
|
1233
|
+
this.store.notifications.unsubscribe(this.___token);
|
|
1234
|
+
}
|
|
1235
|
+
get type() {
|
|
1236
|
+
return this.identifier().type;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
The `id` of the record that this reference refers to.
|
|
1241
|
+
Together, the `type` and `id` properties form a composite key for
|
|
1242
|
+
the identity map.
|
|
1243
|
+
Example
|
|
1244
|
+
```javascript
|
|
1245
|
+
let userRef = store.getReference('user', 1);
|
|
1246
|
+
userRef.id(); // '1'
|
|
1247
|
+
```
|
|
1248
|
+
@method id
|
|
1249
|
+
@public
|
|
1250
|
+
@return {String} The id of the record.
|
|
1251
|
+
*/
|
|
1252
|
+
id() {
|
|
1253
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
1254
|
+
this._ref; // consume the tracked prop
|
|
1255
|
+
return this.___identifier.id;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
/**
|
|
1259
|
+
The `identifier` of the record that this reference refers to.
|
|
1260
|
+
Together, the `type` and `id` properties form a composite key for
|
|
1261
|
+
the identity map.
|
|
1262
|
+
Example
|
|
1263
|
+
```javascript
|
|
1264
|
+
let userRef = store.getReference('user', 1);
|
|
1265
|
+
userRef.identifier(); // '1'
|
|
1266
|
+
```
|
|
1267
|
+
@method identifier
|
|
1268
|
+
@public
|
|
1269
|
+
@return {String} The identifier of the record.
|
|
1270
|
+
*/
|
|
1271
|
+
identifier() {
|
|
1272
|
+
return this.___identifier;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
How the reference will be looked up when it is loaded. Currently
|
|
1277
|
+
this always returns `identity` to signify that a record will be
|
|
870
1278
|
loaded by its `type` and `id`.
|
|
871
1279
|
Example
|
|
872
1280
|
```javascript
|
|
@@ -1177,12 +1585,13 @@ function storeFor(record) {
|
|
|
1177
1585
|
return store;
|
|
1178
1586
|
}
|
|
1179
1587
|
class InstanceCache {
|
|
1180
|
-
__instances = {
|
|
1181
|
-
record: new Map(),
|
|
1182
|
-
reference: new WeakMap()
|
|
1183
|
-
};
|
|
1184
1588
|
constructor(store) {
|
|
1185
1589
|
this.store = store;
|
|
1590
|
+
this.__instances = {
|
|
1591
|
+
record: new Map(),
|
|
1592
|
+
reference: new WeakMap(),
|
|
1593
|
+
document: new Map()
|
|
1594
|
+
};
|
|
1186
1595
|
this._storeWrapper = new CacheCapabilitiesManager(this.store);
|
|
1187
1596
|
store.identifierCache.__configureMerge((identifier, matchedIdentifier, resourceData) => {
|
|
1188
1597
|
let keptIdentifier = identifier;
|
|
@@ -1237,6 +1646,14 @@ class InstanceCache {
|
|
|
1237
1646
|
peek(identifier) {
|
|
1238
1647
|
return this.__instances.record.get(identifier);
|
|
1239
1648
|
}
|
|
1649
|
+
getDocument(identifier) {
|
|
1650
|
+
let doc = this.__instances.document.get(identifier);
|
|
1651
|
+
if (!doc) {
|
|
1652
|
+
doc = new ReactiveDocument(this.store, identifier, null);
|
|
1653
|
+
this.__instances.document.set(identifier, doc);
|
|
1654
|
+
}
|
|
1655
|
+
return doc;
|
|
1656
|
+
}
|
|
1240
1657
|
getRecord(identifier, properties) {
|
|
1241
1658
|
let record = this.__instances.record.get(identifier);
|
|
1242
1659
|
if (!record) {
|
|
@@ -1252,9 +1669,16 @@ class InstanceCache {
|
|
|
1252
1669
|
setCacheFor(record, cache);
|
|
1253
1670
|
StoreMap.set(record, this.store);
|
|
1254
1671
|
this.__instances.record.set(identifier, record);
|
|
1255
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1256
|
-
|
|
1257
|
-
|
|
1672
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1673
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1674
|
+
logGroup('reactive-ui', '', identifier.type, identifier.lid, 'created', '');
|
|
1675
|
+
// eslint-disable-next-line no-console
|
|
1676
|
+
console.log({
|
|
1677
|
+
properties
|
|
1678
|
+
});
|
|
1679
|
+
// eslint-disable-next-line no-console
|
|
1680
|
+
console.groupEnd();
|
|
1681
|
+
}
|
|
1258
1682
|
}
|
|
1259
1683
|
}
|
|
1260
1684
|
return record;
|
|
@@ -1300,9 +1724,10 @@ class InstanceCache {
|
|
|
1300
1724
|
this.store.identifierCache.forgetRecordIdentifier(identifier);
|
|
1301
1725
|
removeRecordDataFor(identifier);
|
|
1302
1726
|
this.store._requestCache._clearEntries(identifier);
|
|
1303
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1304
|
-
|
|
1305
|
-
|
|
1727
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1728
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1729
|
+
log('reactive-ui', '', identifier.type, identifier.lid, 'disconnected', '');
|
|
1730
|
+
}
|
|
1306
1731
|
}
|
|
1307
1732
|
}
|
|
1308
1733
|
unloadRecord(identifier) {
|
|
@@ -1318,9 +1743,11 @@ class InstanceCache {
|
|
|
1318
1743
|
})() : {};
|
|
1319
1744
|
}
|
|
1320
1745
|
}
|
|
1321
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1322
|
-
|
|
1323
|
-
|
|
1746
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1747
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1748
|
+
// eslint-disable-next-line no-console
|
|
1749
|
+
console.groupCollapsed(`InstanceCache: unloading record for ${String(identifier)}`);
|
|
1750
|
+
}
|
|
1324
1751
|
}
|
|
1325
1752
|
|
|
1326
1753
|
// TODO is this join still necessary?
|
|
@@ -1333,27 +1760,33 @@ class InstanceCache {
|
|
|
1333
1760
|
StoreMap.delete(record);
|
|
1334
1761
|
RecordCache.delete(record);
|
|
1335
1762
|
removeRecordDataFor(record);
|
|
1336
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1337
|
-
|
|
1338
|
-
|
|
1763
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1764
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1765
|
+
// eslint-disable-next-line no-console
|
|
1766
|
+
console.log(`InstanceCache: destroyed record for ${String(identifier)}`);
|
|
1767
|
+
}
|
|
1339
1768
|
}
|
|
1340
1769
|
}
|
|
1341
1770
|
if (cache) {
|
|
1342
1771
|
cache.unloadRecord(identifier);
|
|
1343
1772
|
removeRecordDataFor(identifier);
|
|
1344
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1345
|
-
|
|
1346
|
-
|
|
1773
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1774
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1775
|
+
// eslint-disable-next-line no-console
|
|
1776
|
+
console.log(`InstanceCache: destroyed cache for ${String(identifier)}`);
|
|
1777
|
+
}
|
|
1347
1778
|
}
|
|
1348
1779
|
} else {
|
|
1349
1780
|
this.disconnect(identifier);
|
|
1350
1781
|
}
|
|
1351
1782
|
this.store._requestCache._clearEntries(identifier);
|
|
1352
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1783
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1784
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1785
|
+
// eslint-disable-next-line no-console
|
|
1786
|
+
console.log(`InstanceCache: unloaded RecordData for ${String(identifier)}`);
|
|
1787
|
+
// eslint-disable-next-line no-console
|
|
1788
|
+
console.groupEnd();
|
|
1789
|
+
}
|
|
1357
1790
|
}
|
|
1358
1791
|
});
|
|
1359
1792
|
}
|
|
@@ -1408,9 +1841,11 @@ class InstanceCache {
|
|
|
1408
1841
|
warn(`Your ${type} record was saved to the server, but the response does not have an id.`, !(oldId !== null && id === null));
|
|
1409
1842
|
return;
|
|
1410
1843
|
}
|
|
1411
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1412
|
-
|
|
1413
|
-
|
|
1844
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1845
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1846
|
+
// eslint-disable-next-line no-console
|
|
1847
|
+
console.log(`InstanceCache: updating id to '${id}' for record ${String(identifier)}`);
|
|
1848
|
+
}
|
|
1414
1849
|
}
|
|
1415
1850
|
const existingIdentifier = this.store.identifierCache.peekRecordIdentifier({
|
|
1416
1851
|
type,
|
|
@@ -1727,7 +2162,9 @@ class CacheManager {
|
|
|
1727
2162
|
peek(identifier) {
|
|
1728
2163
|
return this.#cache.peek(identifier);
|
|
1729
2164
|
}
|
|
1730
|
-
|
|
2165
|
+
peekRemoteState(identifier) {
|
|
2166
|
+
return this.#cache.peekRemoteState(identifier);
|
|
2167
|
+
}
|
|
1731
2168
|
/**
|
|
1732
2169
|
* Peek the Cache for the existing request data associated with
|
|
1733
2170
|
* a cacheable request
|
|
@@ -1950,6 +2387,19 @@ class CacheManager {
|
|
|
1950
2387
|
return this.#cache.getAttr(identifier, propertyName);
|
|
1951
2388
|
}
|
|
1952
2389
|
|
|
2390
|
+
/**
|
|
2391
|
+
* Retrieve the remote state for an attribute from the cache
|
|
2392
|
+
*
|
|
2393
|
+
* @method getRemoteAttr
|
|
2394
|
+
* @public
|
|
2395
|
+
* @param identifier
|
|
2396
|
+
* @param propertyName
|
|
2397
|
+
* @return {unknown}
|
|
2398
|
+
*/
|
|
2399
|
+
getRemoteAttr(identifier, propertyName) {
|
|
2400
|
+
return this.#cache.getRemoteAttr(identifier, propertyName);
|
|
2401
|
+
}
|
|
2402
|
+
|
|
1953
2403
|
/**
|
|
1954
2404
|
* Mutate the data for an attribute in the cache
|
|
1955
2405
|
*
|
|
@@ -2074,6 +2524,19 @@ class CacheManager {
|
|
|
2074
2524
|
return this.#cache.getRelationship(identifier, propertyName);
|
|
2075
2525
|
}
|
|
2076
2526
|
|
|
2527
|
+
/**
|
|
2528
|
+
* Query the cache for the remote state of a relationship property
|
|
2529
|
+
*
|
|
2530
|
+
* @method getRelationship
|
|
2531
|
+
* @public
|
|
2532
|
+
* @param identifier
|
|
2533
|
+
* @param propertyName
|
|
2534
|
+
* @return resource relationship object
|
|
2535
|
+
*/
|
|
2536
|
+
getRemoteRelationship(identifier, propertyName) {
|
|
2537
|
+
return this.#cache.getRemoteRelationship(identifier, propertyName);
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2077
2540
|
// Resource State
|
|
2078
2541
|
// ===============
|
|
2079
2542
|
|
|
@@ -2158,27 +2621,51 @@ class CacheManager {
|
|
|
2158
2621
|
* @module @ember-data/store
|
|
2159
2622
|
*/
|
|
2160
2623
|
|
|
2161
|
-
let tokenId = 0;
|
|
2162
|
-
const CacheOperations = new Set(['added', 'removed', 'state', 'updated', 'invalidated']);
|
|
2163
2624
|
function isCacheOperationValue(value) {
|
|
2164
|
-
return
|
|
2625
|
+
return value === 'added' || value === 'state' || value === 'updated' || value === 'removed' || value === 'invalidated';
|
|
2165
2626
|
}
|
|
2166
2627
|
function runLoopIsFlushing() {
|
|
2167
2628
|
//@ts-expect-error
|
|
2168
2629
|
return !!_backburner.currentInstance && _backburner._autorun !== true;
|
|
2169
2630
|
}
|
|
2170
|
-
function
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2631
|
+
function count(label) {
|
|
2632
|
+
// @ts-expect-error
|
|
2633
|
+
// eslint-disable-next-line
|
|
2634
|
+
globalThis.__WarpDriveMetricCountData[label] = (globalThis.__WarpDriveMetricCountData[label] || 0) + 1;
|
|
2635
|
+
}
|
|
2636
|
+
function asInternalToken(token) {
|
|
2637
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2638
|
+
if (!test) {
|
|
2639
|
+
throw new Error(`Expected a token with a 'for' property`);
|
|
2640
|
+
}
|
|
2641
|
+
})(token && typeof token === 'function' && 'for' in token) : {};
|
|
2642
|
+
}
|
|
2643
|
+
function _unsubscribe(token, cache) {
|
|
2644
|
+
asInternalToken(token);
|
|
2645
|
+
const identifier = token.for;
|
|
2646
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2647
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2648
|
+
if (!identifier) {
|
|
2649
|
+
// eslint-disable-next-line no-console
|
|
2650
|
+
console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
|
|
2651
|
+
}
|
|
2176
2652
|
}
|
|
2177
2653
|
}
|
|
2178
2654
|
if (identifier) {
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2655
|
+
const callbacks = cache.get(identifier);
|
|
2656
|
+
if (!callbacks) {
|
|
2657
|
+
return;
|
|
2658
|
+
}
|
|
2659
|
+
const index = callbacks.indexOf(token);
|
|
2660
|
+
if (index === -1) {
|
|
2661
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2662
|
+
if (!test) {
|
|
2663
|
+
throw new Error(`Cannot unsubscribe a token that is not subscribed`);
|
|
2664
|
+
}
|
|
2665
|
+
})(index !== -1) : {};
|
|
2666
|
+
return;
|
|
2667
|
+
}
|
|
2668
|
+
callbacks.splice(index, 1);
|
|
2182
2669
|
}
|
|
2183
2670
|
}
|
|
2184
2671
|
|
|
@@ -2199,7 +2686,6 @@ class NotificationManager {
|
|
|
2199
2686
|
this._buffered = new Map();
|
|
2200
2687
|
this._hasFlush = false;
|
|
2201
2688
|
this._cache = new Map();
|
|
2202
|
-
this._tokens = new Map();
|
|
2203
2689
|
}
|
|
2204
2690
|
|
|
2205
2691
|
/**
|
|
@@ -2236,17 +2722,26 @@ class NotificationManager {
|
|
|
2236
2722
|
throw new Error(`Expected to receive a stable Identifier to subscribe to`);
|
|
2237
2723
|
}
|
|
2238
2724
|
})(identifier === 'resource' || identifier === 'document' || isStableIdentifier(identifier) || isDocumentIdentifier(identifier)) : {};
|
|
2239
|
-
let
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2725
|
+
let callbacks = this._cache.get(identifier);
|
|
2726
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2727
|
+
if (!test) {
|
|
2728
|
+
throw new Error(`expected to receive a valid callback`);
|
|
2729
|
+
}
|
|
2730
|
+
})(typeof callback === 'function') : {};
|
|
2731
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2732
|
+
if (!test) {
|
|
2733
|
+
throw new Error(`cannot subscribe with the same callback twice`);
|
|
2734
|
+
}
|
|
2735
|
+
})(!callbacks || !callbacks.includes(callback)) : {};
|
|
2736
|
+
// we use the callback as the cancellation token
|
|
2737
|
+
//@ts-expect-error
|
|
2738
|
+
callback.for = identifier;
|
|
2739
|
+
if (!callbacks) {
|
|
2740
|
+
callbacks = [];
|
|
2741
|
+
this._cache.set(identifier, callbacks);
|
|
2243
2742
|
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
} : {};
|
|
2247
|
-
map.set(unsubToken, callback);
|
|
2248
|
-
this._tokens.set(unsubToken, identifier);
|
|
2249
|
-
return unsubToken;
|
|
2743
|
+
callbacks.push(callback);
|
|
2744
|
+
return callback;
|
|
2250
2745
|
}
|
|
2251
2746
|
|
|
2252
2747
|
/**
|
|
@@ -2258,7 +2753,7 @@ class NotificationManager {
|
|
|
2258
2753
|
*/
|
|
2259
2754
|
unsubscribe(token) {
|
|
2260
2755
|
if (!this.isDestroyed) {
|
|
2261
|
-
_unsubscribe(
|
|
2756
|
+
_unsubscribe(token, this._cache);
|
|
2262
2757
|
}
|
|
2263
2758
|
}
|
|
2264
2759
|
|
|
@@ -2280,17 +2775,15 @@ class NotificationManager {
|
|
|
2280
2775
|
}
|
|
2281
2776
|
})(!key || value === 'attributes' || value === 'relationships') : {};
|
|
2282
2777
|
if (!isStableIdentifier(identifier) && !isDocumentIdentifier(identifier)) {
|
|
2283
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
2284
|
-
|
|
2285
|
-
|
|
2778
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2779
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2780
|
+
// eslint-disable-next-line no-console
|
|
2781
|
+
console.log(`Notifying: Expected to receive a stable Identifier to notify '${value}' '${key || ''}' with, but ${String(identifier)} is not in the cache`, identifier);
|
|
2782
|
+
}
|
|
2286
2783
|
}
|
|
2287
2784
|
return false;
|
|
2288
2785
|
}
|
|
2289
|
-
|
|
2290
|
-
// eslint-disable-next-line no-console
|
|
2291
|
-
console.log(`Buffering Notify: ${String(identifier.lid)}\t${value}\t${key || ''}`);
|
|
2292
|
-
}
|
|
2293
|
-
const hasSubscribers = Boolean(this._cache.get(identifier)?.size);
|
|
2786
|
+
const hasSubscribers = Boolean(this._cache.get(identifier)?.length);
|
|
2294
2787
|
if (isCacheOperationValue(value) || hasSubscribers) {
|
|
2295
2788
|
let buffer = this._buffered.get(identifier);
|
|
2296
2789
|
if (!buffer) {
|
|
@@ -2298,7 +2791,29 @@ class NotificationManager {
|
|
|
2298
2791
|
this._buffered.set(identifier, buffer);
|
|
2299
2792
|
}
|
|
2300
2793
|
buffer.push([value, key]);
|
|
2301
|
-
|
|
2794
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
|
|
2795
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
|
|
2796
|
+
count(`notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
if (!this._scheduleNotify()) {
|
|
2800
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2801
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2802
|
+
log('notify', 'buffered', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
} else {
|
|
2807
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2808
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2809
|
+
log('notify', 'discarded', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
|
|
2813
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
|
|
2814
|
+
count(`DISCARDED notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2302
2817
|
}
|
|
2303
2818
|
return hasSubscribers;
|
|
2304
2819
|
}
|
|
@@ -2309,14 +2824,15 @@ class NotificationManager {
|
|
|
2309
2824
|
const asyncFlush = this.store._enableAsyncFlush;
|
|
2310
2825
|
if (this._hasFlush) {
|
|
2311
2826
|
if (asyncFlush !== false && !runLoopIsFlushing()) {
|
|
2312
|
-
return;
|
|
2827
|
+
return false;
|
|
2313
2828
|
}
|
|
2314
2829
|
}
|
|
2315
2830
|
if (asyncFlush && !runLoopIsFlushing()) {
|
|
2316
2831
|
this._hasFlush = true;
|
|
2317
|
-
return;
|
|
2832
|
+
return false;
|
|
2318
2833
|
}
|
|
2319
2834
|
this._flush();
|
|
2835
|
+
return true;
|
|
2320
2836
|
}
|
|
2321
2837
|
_flush() {
|
|
2322
2838
|
const buffered = this._buffered;
|
|
@@ -2334,9 +2850,10 @@ class NotificationManager {
|
|
|
2334
2850
|
this._onFlushCB = undefined;
|
|
2335
2851
|
}
|
|
2336
2852
|
_flushNotification(identifier, value, key) {
|
|
2337
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
2338
|
-
|
|
2339
|
-
|
|
2853
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2854
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2855
|
+
log('notify', '', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
|
|
2856
|
+
}
|
|
2340
2857
|
}
|
|
2341
2858
|
|
|
2342
2859
|
// TODO for documents this will need to switch based on Identifier kind
|
|
@@ -2348,11 +2865,11 @@ class NotificationManager {
|
|
|
2348
2865
|
});
|
|
2349
2866
|
}
|
|
2350
2867
|
}
|
|
2351
|
-
const
|
|
2352
|
-
if (!
|
|
2868
|
+
const callbacks = this._cache.get(identifier);
|
|
2869
|
+
if (!callbacks || !callbacks.length) {
|
|
2353
2870
|
return false;
|
|
2354
2871
|
}
|
|
2355
|
-
|
|
2872
|
+
callbacks.forEach(cb => {
|
|
2356
2873
|
// @ts-expect-error overload doesn't narrow within body
|
|
2357
2874
|
cb(identifier, value, key);
|
|
2358
2875
|
});
|
|
@@ -2360,7 +2877,6 @@ class NotificationManager {
|
|
|
2360
2877
|
}
|
|
2361
2878
|
destroy() {
|
|
2362
2879
|
this.isDestroyed = true;
|
|
2363
|
-
this._tokens.clear();
|
|
2364
2880
|
this._cache.clear();
|
|
2365
2881
|
}
|
|
2366
2882
|
}
|
|
@@ -2474,6 +2990,7 @@ class IdentifierArray {
|
|
|
2474
2990
|
isDestroying = false;
|
|
2475
2991
|
isDestroyed = false;
|
|
2476
2992
|
_updatingPromise = null;
|
|
2993
|
+
identifier;
|
|
2477
2994
|
[IS_COLLECTION] = true;
|
|
2478
2995
|
[SOURCE];
|
|
2479
2996
|
[NOTIFY]() {
|
|
@@ -2512,6 +3029,7 @@ class IdentifierArray {
|
|
|
2512
3029
|
this.modelName = options.type;
|
|
2513
3030
|
this.store = options.store;
|
|
2514
3031
|
this._manager = options.manager;
|
|
3032
|
+
this.identifier = options.identifier || null;
|
|
2515
3033
|
this[SOURCE] = options.identifiers;
|
|
2516
3034
|
this[ARRAY_SIGNAL] = createSignal(this, 'length');
|
|
2517
3035
|
const store = options.store;
|
|
@@ -2682,7 +3200,7 @@ class IdentifierArray {
|
|
|
2682
3200
|
return false;
|
|
2683
3201
|
}
|
|
2684
3202
|
const original = target[index];
|
|
2685
|
-
const newIdentifier = extractIdentifierFromRecord$
|
|
3203
|
+
const newIdentifier = extractIdentifierFromRecord$2(value);
|
|
2686
3204
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2687
3205
|
if (!test) {
|
|
2688
3206
|
throw new Error(`Expected a record`);
|
|
@@ -2723,9 +3241,18 @@ class IdentifierArray {
|
|
|
2723
3241
|
return Reflect.deleteProperty(target, prop);
|
|
2724
3242
|
},
|
|
2725
3243
|
getPrototypeOf() {
|
|
2726
|
-
return
|
|
3244
|
+
return Array.prototype;
|
|
2727
3245
|
}
|
|
2728
3246
|
});
|
|
3247
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
3248
|
+
Object.defineProperty(this, '__SHOW_ME_THE_DATA_(debug mode only)__', {
|
|
3249
|
+
enumerable: false,
|
|
3250
|
+
configurable: true,
|
|
3251
|
+
get() {
|
|
3252
|
+
return proxy.slice();
|
|
3253
|
+
}
|
|
3254
|
+
});
|
|
3255
|
+
}
|
|
2729
3256
|
createArrayTags(proxy, _SIGNAL);
|
|
2730
3257
|
this[NOTIFY] = this[NOTIFY].bind(proxy);
|
|
2731
3258
|
return proxy;
|
|
@@ -2866,7 +3393,7 @@ Collection.prototype.query = null;
|
|
|
2866
3393
|
// Ensure instanceof works correctly
|
|
2867
3394
|
// Object.setPrototypeOf(IdentifierArray.prototype, Array.prototype);
|
|
2868
3395
|
|
|
2869
|
-
function assertRecordPassedToHasMany(record) {
|
|
3396
|
+
function assertRecordPassedToHasMany$1(record) {
|
|
2870
3397
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2871
3398
|
if (!test) {
|
|
2872
3399
|
throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed $${typeof record}`);
|
|
@@ -2880,11 +3407,11 @@ function assertRecordPassedToHasMany(record) {
|
|
|
2880
3407
|
}
|
|
2881
3408
|
}()) : {};
|
|
2882
3409
|
}
|
|
2883
|
-
function extractIdentifierFromRecord$
|
|
3410
|
+
function extractIdentifierFromRecord$2(record) {
|
|
2884
3411
|
if (!record) {
|
|
2885
3412
|
return null;
|
|
2886
3413
|
}
|
|
2887
|
-
assertRecordPassedToHasMany(record);
|
|
3414
|
+
assertRecordPassedToHasMany$1(record);
|
|
2888
3415
|
return recordIdentifierFor(record);
|
|
2889
3416
|
}
|
|
2890
3417
|
|
|
@@ -2959,6 +3486,12 @@ class RecordArrayManager {
|
|
|
2959
3486
|
this._identifiers = new Map();
|
|
2960
3487
|
this._set = new Map();
|
|
2961
3488
|
this._visibilitySet = new Map();
|
|
3489
|
+
this._subscription = this.store.notifications.subscribe('document', (identifier, type) => {
|
|
3490
|
+
if (type === 'updated' && this._keyedArrays.has(identifier.lid)) {
|
|
3491
|
+
const array = this._keyedArrays.get(identifier.lid);
|
|
3492
|
+
this.dirtyArray(array, 0, true);
|
|
3493
|
+
}
|
|
3494
|
+
});
|
|
2962
3495
|
this._subscription = this.store.notifications.subscribe('resource', (identifier, type) => {
|
|
2963
3496
|
if (type === 'added') {
|
|
2964
3497
|
this._visibilitySet.set(identifier, true);
|
|
@@ -2973,11 +3506,38 @@ class RecordArrayManager {
|
|
|
2973
3506
|
}
|
|
2974
3507
|
_syncArray(array) {
|
|
2975
3508
|
const pending = this._pending.get(array);
|
|
2976
|
-
|
|
3509
|
+
const isRequestArray = isCollection(array);
|
|
3510
|
+
if (!isRequestArray && !pending || this.isDestroying || this.isDestroyed) {
|
|
2977
3511
|
return;
|
|
2978
3512
|
}
|
|
2979
|
-
|
|
2980
|
-
|
|
3513
|
+
|
|
3514
|
+
// first flush any staged changes
|
|
3515
|
+
if (pending) {
|
|
3516
|
+
sync(array, pending, this._set.get(array));
|
|
3517
|
+
this._pending.delete(array);
|
|
3518
|
+
}
|
|
3519
|
+
|
|
3520
|
+
// then pull new state if required
|
|
3521
|
+
if (isRequestArray) {
|
|
3522
|
+
const tag = array[ARRAY_SIGNAL];
|
|
3523
|
+
if (tag.reason === 'cache-sync') {
|
|
3524
|
+
tag.reason = null;
|
|
3525
|
+
const doc = this.store.cache.peek(array.identifier);
|
|
3526
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3527
|
+
if (!test) {
|
|
3528
|
+
throw new Error(`Expected to find a document for ${array.identifier.lid} but found none`);
|
|
3529
|
+
}
|
|
3530
|
+
})(doc) : {};
|
|
3531
|
+
const data = !('data' in doc) || !Array.isArray(doc.data) ? [] : doc.data;
|
|
3532
|
+
// TODO technically we should destroy here if
|
|
3533
|
+
// !('data' in doc) || !Array.isArray(doc.data)
|
|
3534
|
+
// is true.
|
|
3535
|
+
this.populateManagedArray(array, data, null);
|
|
3536
|
+
}
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
mutate(mutation) {
|
|
3540
|
+
this.store.cache.mutate(mutation);
|
|
2981
3541
|
}
|
|
2982
3542
|
|
|
2983
3543
|
/**
|
|
@@ -3013,9 +3573,13 @@ class RecordArrayManager {
|
|
|
3013
3573
|
}
|
|
3014
3574
|
return array;
|
|
3015
3575
|
}
|
|
3016
|
-
|
|
3576
|
+
getCollection(config) {
|
|
3577
|
+
if (config.identifier && this._keyedArrays.has(config.identifier.lid)) {
|
|
3578
|
+
return this._keyedArrays.get(config.identifier.lid);
|
|
3579
|
+
}
|
|
3017
3580
|
const options = {
|
|
3018
3581
|
type: config.type,
|
|
3582
|
+
identifier: config.identifier || null,
|
|
3019
3583
|
links: config.doc?.links || null,
|
|
3020
3584
|
meta: config.doc?.meta || null,
|
|
3021
3585
|
query: config.query || null,
|
|
@@ -3028,16 +3592,22 @@ class RecordArrayManager {
|
|
|
3028
3592
|
const array = new Collection(options);
|
|
3029
3593
|
this._managed.add(array);
|
|
3030
3594
|
this._set.set(array, new Set(options.identifiers || []));
|
|
3595
|
+
if (config.identifier) {
|
|
3596
|
+
this._keyedArrays.set(config.identifier.lid, array);
|
|
3597
|
+
}
|
|
3031
3598
|
if (config.identifiers) {
|
|
3032
3599
|
associate(this._identifiers, array, config.identifiers);
|
|
3033
3600
|
}
|
|
3034
3601
|
return array;
|
|
3035
3602
|
}
|
|
3036
|
-
dirtyArray(array, delta) {
|
|
3603
|
+
dirtyArray(array, delta, shouldSyncFromCache) {
|
|
3037
3604
|
if (array === FAKE_ARR) {
|
|
3038
3605
|
return;
|
|
3039
3606
|
}
|
|
3040
3607
|
const tag = array[ARRAY_SIGNAL];
|
|
3608
|
+
if (shouldSyncFromCache) {
|
|
3609
|
+
tag.reason = 'cache-sync';
|
|
3610
|
+
}
|
|
3041
3611
|
if (!tag.shouldReset) {
|
|
3042
3612
|
tag.shouldReset = true;
|
|
3043
3613
|
addTransactionCB(array[NOTIFY]);
|
|
@@ -3096,13 +3666,18 @@ class RecordArrayManager {
|
|
|
3096
3666
|
populateManagedArray(array, identifiers, payload) {
|
|
3097
3667
|
this._pending.delete(array);
|
|
3098
3668
|
const source = array[SOURCE];
|
|
3669
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
3670
|
+
if (!test) {
|
|
3671
|
+
throw new Error(`The new state of the collection should not be using the same array reference as the original state.`);
|
|
3672
|
+
}
|
|
3673
|
+
})(source !== identifiers) : {};
|
|
3099
3674
|
const old = source.slice();
|
|
3100
3675
|
source.length = 0;
|
|
3101
3676
|
fastPush(source, identifiers);
|
|
3102
3677
|
this._set.set(array, new Set(identifiers));
|
|
3103
3678
|
notifyArray(array);
|
|
3104
|
-
array.meta = payload
|
|
3105
|
-
array.links = payload
|
|
3679
|
+
array.meta = payload?.meta || null;
|
|
3680
|
+
array.links = payload?.links || null;
|
|
3106
3681
|
array.isLoaded = true;
|
|
3107
3682
|
disassociate(this._identifiers, array, old);
|
|
3108
3683
|
associate(this._identifiers, array, identifiers);
|
|
@@ -3116,7 +3691,7 @@ class RecordArrayManager {
|
|
|
3116
3691
|
changes.delete(identifier);
|
|
3117
3692
|
} else {
|
|
3118
3693
|
changes.set(identifier, 'add');
|
|
3119
|
-
this.dirtyArray(array, changes.size);
|
|
3694
|
+
this.dirtyArray(array, changes.size, false);
|
|
3120
3695
|
}
|
|
3121
3696
|
});
|
|
3122
3697
|
}
|
|
@@ -3130,7 +3705,7 @@ class RecordArrayManager {
|
|
|
3130
3705
|
changes.delete(identifier);
|
|
3131
3706
|
} else {
|
|
3132
3707
|
changes.set(identifier, 'del');
|
|
3133
|
-
this.dirtyArray(array, changes.size);
|
|
3708
|
+
this.dirtyArray(array, changes.size, false);
|
|
3134
3709
|
}
|
|
3135
3710
|
});
|
|
3136
3711
|
}
|
|
@@ -3235,6 +3810,9 @@ function sync(array, changes, arraySet) {
|
|
|
3235
3810
|
*/
|
|
3236
3811
|
}
|
|
3237
3812
|
}
|
|
3813
|
+
function isCollection(array) {
|
|
3814
|
+
return array.identifier !== null;
|
|
3815
|
+
}
|
|
3238
3816
|
|
|
3239
3817
|
/**
|
|
3240
3818
|
* @module @ember-data/store
|
|
@@ -3495,6 +4073,118 @@ function constructResource(type, id, lid) {
|
|
|
3495
4073
|
*/
|
|
3496
4074
|
// this import location is deprecated but breaks in 4.8 and older
|
|
3497
4075
|
|
|
4076
|
+
// @ts-expect-error adding to globalThis
|
|
4077
|
+
globalThis.setWarpDriveLogging = setLogging;
|
|
4078
|
+
|
|
4079
|
+
// @ts-expect-error adding to globalThis
|
|
4080
|
+
globalThis.getWarpDriveRuntimeConfig = getRuntimeConfig;
|
|
4081
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
|
|
4082
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
|
|
4083
|
+
// @ts-expect-error adding to globalThis
|
|
4084
|
+
// eslint-disable-next-line
|
|
4085
|
+
globalThis.__WarpDriveMetricCountData = globalThis.__WarpDriveMetricCountData || {};
|
|
4086
|
+
|
|
4087
|
+
// @ts-expect-error adding to globalThis
|
|
4088
|
+
globalThis.getWarpDriveMetricCounts = () => {
|
|
4089
|
+
// @ts-expect-error
|
|
4090
|
+
// eslint-disable-next-line
|
|
4091
|
+
return structuredClone(globalThis.__WarpDriveMetricCountData);
|
|
4092
|
+
};
|
|
4093
|
+
|
|
4094
|
+
// @ts-expect-error adding to globalThis
|
|
4095
|
+
globalThis.resetWarpDriveMetricCounts = () => {
|
|
4096
|
+
// @ts-expect-error
|
|
4097
|
+
globalThis.__WarpDriveMetricCountData = {};
|
|
4098
|
+
};
|
|
4099
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS)) {
|
|
4100
|
+
if (getGlobalConfig().WarpDrive.debug.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS) {
|
|
4101
|
+
// @ts-expect-error adding to globalThis
|
|
4102
|
+
globalThis.__primitiveInstanceId = 0;
|
|
4103
|
+
function interceptAndLog(klassName, methodName) {
|
|
4104
|
+
const klass = globalThis[klassName];
|
|
4105
|
+
if (methodName === 'constructor') {
|
|
4106
|
+
const instantiationLabel = `new ${klassName}()`;
|
|
4107
|
+
// @ts-expect-error
|
|
4108
|
+
globalThis[klassName] = class extends klass {
|
|
4109
|
+
// @ts-expect-error
|
|
4110
|
+
constructor(...args) {
|
|
4111
|
+
// eslint-disable-next-line
|
|
4112
|
+
super(...args);
|
|
4113
|
+
// @ts-expect-error
|
|
4114
|
+
|
|
4115
|
+
const instanceId = globalThis.__primitiveInstanceId++;
|
|
4116
|
+
// @ts-expect-error
|
|
4117
|
+
// eslint-disable-next-line
|
|
4118
|
+
globalThis.__WarpDriveMetricCountData[instantiationLabel] =
|
|
4119
|
+
// @ts-expect-error
|
|
4120
|
+
// eslint-disable-next-line
|
|
4121
|
+
(globalThis.__WarpDriveMetricCountData[instantiationLabel] || 0) + 1;
|
|
4122
|
+
// @ts-expect-error
|
|
4123
|
+
this.instanceName = `${klassName}:${instanceId} - ${new Error().stack?.split('\n')[2]}`;
|
|
4124
|
+
}
|
|
4125
|
+
};
|
|
4126
|
+
} else {
|
|
4127
|
+
// @ts-expect-error
|
|
4128
|
+
// eslint-disable-next-line
|
|
4129
|
+
const original = klass.prototype[methodName];
|
|
4130
|
+
const logName = `${klassName}.${methodName}`;
|
|
4131
|
+
|
|
4132
|
+
// @ts-expect-error
|
|
4133
|
+
klass.prototype[methodName] = function (...args) {
|
|
4134
|
+
// @ts-expect-error
|
|
4135
|
+
// eslint-disable-next-line
|
|
4136
|
+
globalThis.__WarpDriveMetricCountData[logName] = (globalThis.__WarpDriveMetricCountData[logName] || 0) + 1;
|
|
4137
|
+
// @ts-expect-error
|
|
4138
|
+
const {
|
|
4139
|
+
instanceName
|
|
4140
|
+
} = this;
|
|
4141
|
+
if (!instanceName) {
|
|
4142
|
+
// @ts-expect-error
|
|
4143
|
+
const instanceId = globalThis.__primitiveInstanceId++;
|
|
4144
|
+
// @ts-expect-error
|
|
4145
|
+
this.instanceName = `${klassName}.${methodName}:${instanceId} - ${new Error().stack?.split('\n')[2]}`;
|
|
4146
|
+
}
|
|
4147
|
+
const instanceLogName = `${logName} (${instanceName})`;
|
|
4148
|
+
// @ts-expect-error
|
|
4149
|
+
// eslint-disable-next-line
|
|
4150
|
+
globalThis.__WarpDriveMetricCountData[instanceLogName] =
|
|
4151
|
+
// @ts-expect-error
|
|
4152
|
+
// eslint-disable-next-line
|
|
4153
|
+
(globalThis.__WarpDriveMetricCountData[instanceLogName] || 0) + 1;
|
|
4154
|
+
// eslint-disable-next-line
|
|
4155
|
+
return original.apply(this, args);
|
|
4156
|
+
};
|
|
4157
|
+
}
|
|
4158
|
+
}
|
|
4159
|
+
interceptAndLog('Set', 'constructor');
|
|
4160
|
+
interceptAndLog('Set', 'add');
|
|
4161
|
+
interceptAndLog('Set', 'delete');
|
|
4162
|
+
interceptAndLog('Set', 'has');
|
|
4163
|
+
interceptAndLog('Set', 'set');
|
|
4164
|
+
interceptAndLog('Set', 'get');
|
|
4165
|
+
interceptAndLog('Map', 'constructor');
|
|
4166
|
+
interceptAndLog('Map', 'set');
|
|
4167
|
+
interceptAndLog('Map', 'delete');
|
|
4168
|
+
interceptAndLog('Map', 'has');
|
|
4169
|
+
interceptAndLog('Map', 'add');
|
|
4170
|
+
interceptAndLog('Map', 'get');
|
|
4171
|
+
interceptAndLog('WeakSet', 'constructor');
|
|
4172
|
+
interceptAndLog('WeakSet', 'add');
|
|
4173
|
+
interceptAndLog('WeakSet', 'delete');
|
|
4174
|
+
interceptAndLog('WeakSet', 'has');
|
|
4175
|
+
interceptAndLog('WeakSet', 'set');
|
|
4176
|
+
interceptAndLog('WeakSet', 'get');
|
|
4177
|
+
interceptAndLog('WeakMap', 'constructor');
|
|
4178
|
+
interceptAndLog('WeakMap', 'set');
|
|
4179
|
+
interceptAndLog('WeakMap', 'delete');
|
|
4180
|
+
interceptAndLog('WeakMap', 'has');
|
|
4181
|
+
interceptAndLog('WeakMap', 'add');
|
|
4182
|
+
interceptAndLog('WeakMap', 'get');
|
|
4183
|
+
}
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
}
|
|
4187
|
+
|
|
3498
4188
|
// `AwaitedKeys` is needed here to resolve any promise types like `PromiseBelongsTo`.
|
|
3499
4189
|
|
|
3500
4190
|
/**
|
|
@@ -3561,6 +4251,7 @@ const app = new EmberApp(defaults, {
|
|
|
3561
4251
|
id: 'ember-data:deprecate-store-extends-ember-object',
|
|
3562
4252
|
until: '6.0',
|
|
3563
4253
|
for: 'ember-data',
|
|
4254
|
+
url: 'https://deprecations.emberjs.com/id/ember-data-deprecate-store-extends-ember-object',
|
|
3564
4255
|
since: {
|
|
3565
4256
|
available: '4.13',
|
|
3566
4257
|
enabled: '5.4'
|
|
@@ -3708,7 +4399,6 @@ class Store extends BaseClass {
|
|
|
3708
4399
|
// private
|
|
3709
4400
|
this._requestCache = new RequestStateService(this);
|
|
3710
4401
|
this._instanceCache = new InstanceCache(this);
|
|
3711
|
-
this._documentCache = new Map();
|
|
3712
4402
|
this.isDestroying = false;
|
|
3713
4403
|
this.isDestroyed = false;
|
|
3714
4404
|
}
|
|
@@ -3877,22 +4567,26 @@ class Store extends BaseClass {
|
|
|
3877
4567
|
opts.disableTestWaiter = typeof requestConfig.disableTestWaiter === 'boolean' ? requestConfig.disableTestWaiter : true;
|
|
3878
4568
|
}
|
|
3879
4569
|
}
|
|
3880
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
4570
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_REQUESTS)) {
|
|
4571
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_REQUESTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_REQUESTS) {
|
|
4572
|
+
let options;
|
|
4573
|
+
try {
|
|
4574
|
+
options = JSON.parse(JSON.stringify(requestConfig));
|
|
4575
|
+
} catch {
|
|
4576
|
+
options = requestConfig;
|
|
4577
|
+
}
|
|
4578
|
+
// eslint-disable-next-line no-console
|
|
4579
|
+
console.log(`request: [[START]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`, options);
|
|
3886
4580
|
}
|
|
3887
|
-
// eslint-disable-next-line no-console
|
|
3888
|
-
console.log(`request: [[START]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`, options);
|
|
3889
4581
|
}
|
|
3890
4582
|
const request = Object.assign({}, requestConfig, opts);
|
|
3891
4583
|
const future = this.requestManager.request(request);
|
|
3892
4584
|
future.onFinalize(() => {
|
|
3893
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
3894
|
-
|
|
3895
|
-
|
|
4585
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_REQUESTS)) {
|
|
4586
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_REQUESTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_REQUESTS) {
|
|
4587
|
+
// eslint-disable-next-line no-console
|
|
4588
|
+
console.log(`request: [[FINALIZE]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`);
|
|
4589
|
+
}
|
|
3896
4590
|
}
|
|
3897
4591
|
// skip flush for legacy belongsTo
|
|
3898
4592
|
if (requestConfig.op === 'findBelongsTo' && !requestConfig.url) {
|
|
@@ -4098,9 +4792,8 @@ class Store extends BaseClass {
|
|
|
4098
4792
|
This will cause the record to be destroyed and freed up for garbage collection.
|
|
4099
4793
|
Example
|
|
4100
4794
|
```javascript
|
|
4101
|
-
store.findRecord('post', '1')
|
|
4102
|
-
|
|
4103
|
-
});
|
|
4795
|
+
const { content: { data: post } } = await store.request(findRecord({ type: 'post', id: '1' }));
|
|
4796
|
+
store.unloadRecord(post);
|
|
4104
4797
|
```
|
|
4105
4798
|
@method unloadRecord
|
|
4106
4799
|
@public
|
|
@@ -5152,16 +5845,6 @@ class Store extends BaseClass {
|
|
|
5152
5845
|
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5153
5846
|
assertDestroyingStore(this, '_push');
|
|
5154
5847
|
}
|
|
5155
|
-
if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_PAYLOADS)) {
|
|
5156
|
-
try {
|
|
5157
|
-
const data = JSON.parse(JSON.stringify(jsonApiDoc));
|
|
5158
|
-
// eslint-disable-next-line no-console
|
|
5159
|
-
console.log('EmberData | Payload - push', data);
|
|
5160
|
-
} catch {
|
|
5161
|
-
// eslint-disable-next-line no-console
|
|
5162
|
-
console.log('EmberData | Payload - push', jsonApiDoc);
|
|
5163
|
-
}
|
|
5164
|
-
}
|
|
5165
5848
|
if (asyncFlush) {
|
|
5166
5849
|
this._enableAsyncFlush = true;
|
|
5167
5850
|
}
|
|
@@ -5382,9 +6065,9 @@ function normalizeProperties(store, identifier, properties) {
|
|
|
5382
6065
|
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5383
6066
|
assertRecordsPassedToHasMany(properties[prop]);
|
|
5384
6067
|
}
|
|
5385
|
-
properties[prop] = extractIdentifiersFromRecords(properties[prop]);
|
|
6068
|
+
properties[prop] = extractIdentifiersFromRecords$1(properties[prop]);
|
|
5386
6069
|
} else if (field.kind === 'belongsTo') {
|
|
5387
|
-
properties[prop] = extractIdentifierFromRecord(properties[prop]);
|
|
6070
|
+
properties[prop] = extractIdentifierFromRecord$1(properties[prop]);
|
|
5388
6071
|
}
|
|
5389
6072
|
}
|
|
5390
6073
|
}
|
|
@@ -5412,222 +6095,16 @@ function assertRecordsPassedToHasMany(records) {
|
|
|
5412
6095
|
});
|
|
5413
6096
|
}()) : {};
|
|
5414
6097
|
}
|
|
5415
|
-
function extractIdentifiersFromRecords(records) {
|
|
5416
|
-
return records.map(record => extractIdentifierFromRecord(record));
|
|
6098
|
+
function extractIdentifiersFromRecords$1(records) {
|
|
6099
|
+
return records.map(record => extractIdentifierFromRecord$1(record));
|
|
5417
6100
|
}
|
|
5418
|
-
function extractIdentifierFromRecord(recordOrPromiseRecord) {
|
|
6101
|
+
function extractIdentifierFromRecord$1(recordOrPromiseRecord) {
|
|
5419
6102
|
if (!recordOrPromiseRecord) {
|
|
5420
6103
|
return null;
|
|
5421
6104
|
}
|
|
5422
6105
|
const extract = recordIdentifierFor;
|
|
5423
6106
|
return extract(recordOrPromiseRecord);
|
|
5424
6107
|
}
|
|
5425
|
-
|
|
5426
|
-
/**
|
|
5427
|
-
* @module @ember-data/store
|
|
5428
|
-
*/
|
|
5429
|
-
function urlFromLink(link) {
|
|
5430
|
-
if (typeof link === 'string') return link;
|
|
5431
|
-
return link.href;
|
|
5432
|
-
}
|
|
5433
|
-
|
|
5434
|
-
/**
|
|
5435
|
-
* A Document is a class that wraps the response content from a request to the API
|
|
5436
|
-
* returned by `Cache.put` or `Cache.peek`, converting resource-identifiers into
|
|
5437
|
-
* record instances.
|
|
5438
|
-
*
|
|
5439
|
-
* It is not directly instantiated by the user, and its properties should not
|
|
5440
|
-
* be directly modified. Whether individual properties are mutable or not is
|
|
5441
|
-
* determined by the record instance itself.
|
|
5442
|
-
*
|
|
5443
|
-
* @public
|
|
5444
|
-
* @class Document
|
|
5445
|
-
*/
|
|
5446
|
-
class Document {
|
|
5447
|
-
/**
|
|
5448
|
-
* The links object for this document, if any
|
|
5449
|
-
*
|
|
5450
|
-
* e.g.
|
|
5451
|
-
*
|
|
5452
|
-
* ```
|
|
5453
|
-
* {
|
|
5454
|
-
* self: '/articles?page[number]=3',
|
|
5455
|
-
* }
|
|
5456
|
-
* ```
|
|
5457
|
-
*
|
|
5458
|
-
* @property links
|
|
5459
|
-
* @type {object|undefined} - a links object
|
|
5460
|
-
* @public
|
|
5461
|
-
*/
|
|
5462
|
-
|
|
5463
|
-
/**
|
|
5464
|
-
* The primary data for this document, if any.
|
|
5465
|
-
*
|
|
5466
|
-
* If this document has no primary data (e.g. because it is an error document)
|
|
5467
|
-
* this property will be `undefined`.
|
|
5468
|
-
*
|
|
5469
|
-
* For collections this will be an array of record instances,
|
|
5470
|
-
* for single resource requests it will be a single record instance or null.
|
|
5471
|
-
*
|
|
5472
|
-
* @property data
|
|
5473
|
-
* @public
|
|
5474
|
-
* @type {object|Array<object>|null|undefined} - a data object
|
|
5475
|
-
*/
|
|
5476
|
-
|
|
5477
|
-
/**
|
|
5478
|
-
* The errors returned by the API for this request, if any
|
|
5479
|
-
*
|
|
5480
|
-
* @property errors
|
|
5481
|
-
* @public
|
|
5482
|
-
* @type {object|undefined} - an errors object
|
|
5483
|
-
*/
|
|
5484
|
-
|
|
5485
|
-
/**
|
|
5486
|
-
* The meta object for this document, if any
|
|
5487
|
-
*
|
|
5488
|
-
* @property meta
|
|
5489
|
-
* @public
|
|
5490
|
-
* @type {object|undefined} - a meta object
|
|
5491
|
-
*/
|
|
5492
|
-
|
|
5493
|
-
/**
|
|
5494
|
-
* The identifier associated with this document, if any
|
|
5495
|
-
*
|
|
5496
|
-
* @property identifier
|
|
5497
|
-
* @public
|
|
5498
|
-
* @type {StableDocumentIdentifier|null}
|
|
5499
|
-
*/
|
|
5500
|
-
|
|
5501
|
-
#store;
|
|
5502
|
-
constructor(store, identifier) {
|
|
5503
|
-
this.#store = store;
|
|
5504
|
-
this.identifier = identifier;
|
|
5505
|
-
}
|
|
5506
|
-
async #request(link, options) {
|
|
5507
|
-
const href = this.links?.[link];
|
|
5508
|
-
if (!href) {
|
|
5509
|
-
return null;
|
|
5510
|
-
}
|
|
5511
|
-
options.method = options.method || 'GET';
|
|
5512
|
-
Object.assign(options, {
|
|
5513
|
-
url: urlFromLink(href)
|
|
5514
|
-
});
|
|
5515
|
-
const response = await this.#store.request(options);
|
|
5516
|
-
return response.content;
|
|
5517
|
-
}
|
|
5518
|
-
|
|
5519
|
-
/**
|
|
5520
|
-
* Fetches the related link for this document, returning a promise that resolves
|
|
5521
|
-
* with the document when the request completes. If no related link is present,
|
|
5522
|
-
* will fallback to the self link if present
|
|
5523
|
-
*
|
|
5524
|
-
* @method fetch
|
|
5525
|
-
* @public
|
|
5526
|
-
* @param {object} options
|
|
5527
|
-
* @return Promise<Document>
|
|
5528
|
-
*/
|
|
5529
|
-
fetch(options = {}) {
|
|
5530
|
-
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5531
|
-
if (!test) {
|
|
5532
|
-
throw new Error(`No self or related link`);
|
|
5533
|
-
}
|
|
5534
|
-
})(this.links?.related || this.links?.self) : {};
|
|
5535
|
-
options.cacheOptions = options.cacheOptions || {};
|
|
5536
|
-
options.cacheOptions.key = this.identifier?.lid;
|
|
5537
|
-
return this.#request(this.links.related ? 'related' : 'self', options);
|
|
5538
|
-
}
|
|
5539
|
-
|
|
5540
|
-
/**
|
|
5541
|
-
* Fetches the next link for this document, returning a promise that resolves
|
|
5542
|
-
* with the new document when the request completes, or null if there is no
|
|
5543
|
-
* next link.
|
|
5544
|
-
*
|
|
5545
|
-
* @method next
|
|
5546
|
-
* @public
|
|
5547
|
-
* @param {object} options
|
|
5548
|
-
* @return Promise<Document | null>
|
|
5549
|
-
*/
|
|
5550
|
-
next(options = {}) {
|
|
5551
|
-
return this.#request('next', options);
|
|
5552
|
-
}
|
|
5553
|
-
|
|
5554
|
-
/**
|
|
5555
|
-
* Fetches the prev link for this document, returning a promise that resolves
|
|
5556
|
-
* with the new document when the request completes, or null if there is no
|
|
5557
|
-
* prev link.
|
|
5558
|
-
*
|
|
5559
|
-
* @method prev
|
|
5560
|
-
* @public
|
|
5561
|
-
* @param {object} options
|
|
5562
|
-
* @return Promise<Document | null>
|
|
5563
|
-
*/
|
|
5564
|
-
prev(options = {}) {
|
|
5565
|
-
return this.#request('prev', options);
|
|
5566
|
-
}
|
|
5567
|
-
|
|
5568
|
-
/**
|
|
5569
|
-
* Fetches the first link for this document, returning a promise that resolves
|
|
5570
|
-
* with the new document when the request completes, or null if there is no
|
|
5571
|
-
* first link.
|
|
5572
|
-
*
|
|
5573
|
-
* @method first
|
|
5574
|
-
* @public
|
|
5575
|
-
* @param {object} options
|
|
5576
|
-
* @return Promise<Document | null>
|
|
5577
|
-
*/
|
|
5578
|
-
first(options = {}) {
|
|
5579
|
-
return this.#request('first', options);
|
|
5580
|
-
}
|
|
5581
|
-
|
|
5582
|
-
/**
|
|
5583
|
-
* Fetches the last link for this document, returning a promise that resolves
|
|
5584
|
-
* with the new document when the request completes, or null if there is no
|
|
5585
|
-
* last link.
|
|
5586
|
-
*
|
|
5587
|
-
* @method last
|
|
5588
|
-
* @public
|
|
5589
|
-
* @param {object} options
|
|
5590
|
-
* @return Promise<Document | null>
|
|
5591
|
-
*/
|
|
5592
|
-
last(options = {}) {
|
|
5593
|
-
return this.#request('last', options);
|
|
5594
|
-
}
|
|
5595
|
-
|
|
5596
|
-
/**
|
|
5597
|
-
* Implemented for `JSON.stringify` support.
|
|
5598
|
-
*
|
|
5599
|
-
* Returns the JSON representation of the document wrapper.
|
|
5600
|
-
*
|
|
5601
|
-
* This is a shallow serialization, it does not deeply serialize
|
|
5602
|
-
* the document's contents, leaving that to the individual record
|
|
5603
|
-
* instances to determine how to do, if at all.
|
|
5604
|
-
*
|
|
5605
|
-
* @method toJSON
|
|
5606
|
-
* @public
|
|
5607
|
-
* @return
|
|
5608
|
-
*/
|
|
5609
|
-
toJSON() {
|
|
5610
|
-
const data = {};
|
|
5611
|
-
data.identifier = this.identifier;
|
|
5612
|
-
if (this.data !== undefined) {
|
|
5613
|
-
data.data = this.data;
|
|
5614
|
-
}
|
|
5615
|
-
if (this.links !== undefined) {
|
|
5616
|
-
data.links = this.links;
|
|
5617
|
-
}
|
|
5618
|
-
if (this.errors !== undefined) {
|
|
5619
|
-
data.errors = this.errors;
|
|
5620
|
-
}
|
|
5621
|
-
if (this.meta !== undefined) {
|
|
5622
|
-
data.meta = this.meta;
|
|
5623
|
-
}
|
|
5624
|
-
return data;
|
|
5625
|
-
}
|
|
5626
|
-
}
|
|
5627
|
-
defineSignal(Document.prototype, 'data');
|
|
5628
|
-
defineSignal(Document.prototype, 'links');
|
|
5629
|
-
defineSignal(Document.prototype, 'errors');
|
|
5630
|
-
defineSignal(Document.prototype, 'meta');
|
|
5631
6108
|
const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);
|
|
5632
6109
|
function calcShouldFetch(store, request, hasCachedValue, identifier) {
|
|
5633
6110
|
const {
|
|
@@ -5644,17 +6121,6 @@ function calcShouldBackgroundFetch(store, request, willFetch, identifier) {
|
|
|
5644
6121
|
function isMutation(request) {
|
|
5645
6122
|
return Boolean(request.op && MUTATION_OPS.has(request.op));
|
|
5646
6123
|
}
|
|
5647
|
-
function copyDocumentProperties(target, source) {
|
|
5648
|
-
if ('links' in source) {
|
|
5649
|
-
target.links = source.links;
|
|
5650
|
-
}
|
|
5651
|
-
if ('meta' in source) {
|
|
5652
|
-
target.meta = source.meta;
|
|
5653
|
-
}
|
|
5654
|
-
if ('errors' in source) {
|
|
5655
|
-
target.errors = source.errors;
|
|
5656
|
-
}
|
|
5657
|
-
}
|
|
5658
6124
|
function isCacheAffecting(document) {
|
|
5659
6125
|
if (!isMutation(document.request)) {
|
|
5660
6126
|
return true;
|
|
@@ -5682,9 +6148,6 @@ function cloneError(error) {
|
|
|
5682
6148
|
Object.assign(cloned, error);
|
|
5683
6149
|
return cloned;
|
|
5684
6150
|
}
|
|
5685
|
-
function isErrorDocument(document) {
|
|
5686
|
-
return 'errors' in document;
|
|
5687
|
-
}
|
|
5688
6151
|
function getPriority(identifier, deduped, priority) {
|
|
5689
6152
|
if (identifier) {
|
|
5690
6153
|
const existing = deduped.get(identifier);
|
|
@@ -5814,10 +6277,10 @@ const CacheHandler = {
|
|
|
5814
6277
|
const shouldHydrate = context.request[EnableHydration] || false;
|
|
5815
6278
|
context.setResponse(peeked.response);
|
|
5816
6279
|
if ('error' in peeked) {
|
|
5817
|
-
const content = shouldHydrate ?
|
|
6280
|
+
const content = shouldHydrate ? maybeUpdateUiObjects(store, context.request, {
|
|
5818
6281
|
shouldHydrate,
|
|
5819
6282
|
identifier
|
|
5820
|
-
}, peeked.content
|
|
6283
|
+
}, peeked.content) : peeked.content;
|
|
5821
6284
|
const newError = cloneError(peeked);
|
|
5822
6285
|
newError.content = content;
|
|
5823
6286
|
throw newError;
|
|
@@ -5825,15 +6288,15 @@ const CacheHandler = {
|
|
|
5825
6288
|
const result = shouldHydrate ? maybeUpdateUiObjects(store, context.request, {
|
|
5826
6289
|
shouldHydrate,
|
|
5827
6290
|
identifier
|
|
5828
|
-
}, peeked.content
|
|
6291
|
+
}, peeked.content) : peeked.content;
|
|
5829
6292
|
return result;
|
|
5830
6293
|
}
|
|
5831
6294
|
};
|
|
5832
|
-
function maybeUpdateUiObjects(store, request, options, document
|
|
6295
|
+
function maybeUpdateUiObjects(store, request, options, document) {
|
|
5833
6296
|
const {
|
|
5834
6297
|
identifier
|
|
5835
6298
|
} = options;
|
|
5836
|
-
if (!document) {
|
|
6299
|
+
if (!document || !options.shouldHydrate) {
|
|
5837
6300
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
5838
6301
|
if (!test) {
|
|
5839
6302
|
throw new Error(`The CacheHandler expected response content but none was found`);
|
|
@@ -5841,97 +6304,16 @@ function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
|
|
|
5841
6304
|
})(!options.shouldHydrate) : {};
|
|
5842
6305
|
return document;
|
|
5843
6306
|
}
|
|
5844
|
-
if (Array.isArray(document.data)) {
|
|
5845
|
-
const {
|
|
5846
|
-
recordArrayManager
|
|
5847
|
-
} = store;
|
|
5848
|
-
if (!identifier) {
|
|
5849
|
-
if (!options.shouldHydrate) {
|
|
5850
|
-
return document;
|
|
5851
|
-
}
|
|
5852
|
-
const data = recordArrayManager.createArray({
|
|
5853
|
-
type: request.url,
|
|
5854
|
-
identifiers: document.data,
|
|
5855
|
-
doc: document,
|
|
5856
|
-
query: request
|
|
5857
|
-
});
|
|
5858
|
-
const doc = new Document(store, null);
|
|
5859
|
-
doc.data = data;
|
|
5860
|
-
doc.meta = document.meta;
|
|
5861
|
-
doc.links = document.links;
|
|
5862
|
-
return doc;
|
|
5863
|
-
}
|
|
5864
|
-
let managed = recordArrayManager._keyedArrays.get(identifier.lid);
|
|
5865
|
-
if (!managed) {
|
|
5866
|
-
managed = recordArrayManager.createArray({
|
|
5867
|
-
type: identifier.lid,
|
|
5868
|
-
identifiers: document.data,
|
|
5869
|
-
doc: document
|
|
5870
|
-
});
|
|
5871
|
-
recordArrayManager._keyedArrays.set(identifier.lid, managed);
|
|
5872
|
-
const doc = new Document(store, identifier);
|
|
5873
|
-
doc.data = managed;
|
|
5874
|
-
doc.meta = document.meta;
|
|
5875
|
-
doc.links = document.links;
|
|
5876
|
-
store._documentCache.set(identifier, doc);
|
|
5877
|
-
return options.shouldHydrate ? doc : document;
|
|
5878
|
-
} else {
|
|
5879
|
-
const doc = store._documentCache.get(identifier);
|
|
5880
|
-
if (!isFromCache) {
|
|
5881
|
-
recordArrayManager.populateManagedArray(managed, document.data, document);
|
|
5882
|
-
doc.data = managed;
|
|
5883
|
-
doc.meta = document.meta;
|
|
5884
|
-
doc.links = document.links;
|
|
5885
|
-
}
|
|
5886
|
-
return options.shouldHydrate ? doc : document;
|
|
5887
|
-
}
|
|
5888
|
-
} else {
|
|
5889
|
-
if (!identifier && !options.shouldHydrate) {
|
|
5890
|
-
return document;
|
|
5891
|
-
}
|
|
5892
|
-
const data = document.data ? store.peekRecord(document.data) : null;
|
|
5893
|
-
let doc;
|
|
5894
|
-
if (identifier) {
|
|
5895
|
-
doc = store._documentCache.get(identifier);
|
|
5896
|
-
}
|
|
5897
|
-
if (!doc) {
|
|
5898
|
-
doc = new Document(store, identifier);
|
|
5899
|
-
doc.data = data;
|
|
5900
|
-
copyDocumentProperties(doc, document);
|
|
5901
|
-
if (identifier) {
|
|
5902
|
-
store._documentCache.set(identifier, doc);
|
|
5903
|
-
}
|
|
5904
|
-
} else if (!isFromCache) {
|
|
5905
|
-
doc.data = data;
|
|
5906
|
-
copyDocumentProperties(doc, document);
|
|
5907
|
-
}
|
|
5908
|
-
return options.shouldHydrate ? doc : document;
|
|
5909
|
-
}
|
|
5910
|
-
}
|
|
5911
|
-
function maybeUpdateErrorUiObjects(store, options, document, isFromCache) {
|
|
5912
|
-
const {
|
|
5913
|
-
identifier
|
|
5914
|
-
} = options;
|
|
5915
|
-
|
|
5916
|
-
// TODO investigate why ResourceErrorDocument is insufficient for expressing all error types
|
|
5917
|
-
if (!isErrorDocument(document) || !identifier && !options.shouldHydrate) {
|
|
5918
|
-
return document;
|
|
5919
|
-
}
|
|
5920
|
-
let doc;
|
|
5921
6307
|
if (identifier) {
|
|
5922
|
-
|
|
5923
|
-
}
|
|
5924
|
-
if (!doc) {
|
|
5925
|
-
doc = new Document(store, identifier);
|
|
5926
|
-
copyDocumentProperties(doc, document);
|
|
5927
|
-
if (identifier) {
|
|
5928
|
-
store._documentCache.set(identifier, doc);
|
|
5929
|
-
}
|
|
5930
|
-
} else if (!isFromCache) {
|
|
5931
|
-
doc.data = undefined;
|
|
5932
|
-
copyDocumentProperties(doc, document);
|
|
6308
|
+
return store._instanceCache.getDocument(identifier);
|
|
5933
6309
|
}
|
|
5934
|
-
|
|
6310
|
+
|
|
6311
|
+
// if we don't have an identifier, we give the document
|
|
6312
|
+
// its own local cache
|
|
6313
|
+
return new ReactiveDocument(store, null, {
|
|
6314
|
+
request,
|
|
6315
|
+
document
|
|
6316
|
+
});
|
|
5935
6317
|
}
|
|
5936
6318
|
function updateCacheForSuccess(store, request, options, document) {
|
|
5937
6319
|
let response = null;
|
|
@@ -5949,7 +6331,7 @@ function updateCacheForSuccess(store, request, options, document) {
|
|
|
5949
6331
|
} else {
|
|
5950
6332
|
response = store.cache.put(document);
|
|
5951
6333
|
}
|
|
5952
|
-
return maybeUpdateUiObjects(store, request, options, response
|
|
6334
|
+
return maybeUpdateUiObjects(store, request, options, response);
|
|
5953
6335
|
}
|
|
5954
6336
|
function handleFetchSuccess(store, context, options, document) {
|
|
5955
6337
|
const {
|
|
@@ -5982,7 +6364,7 @@ function updateCacheForError(store, context, options, error) {
|
|
|
5982
6364
|
store.cache.commitWasRejected(record, errors);
|
|
5983
6365
|
} else {
|
|
5984
6366
|
response = store.cache.put(error);
|
|
5985
|
-
return
|
|
6367
|
+
return maybeUpdateUiObjects(store, context.request, options, response);
|
|
5986
6368
|
}
|
|
5987
6369
|
}
|
|
5988
6370
|
function handleFetchError(store, context, options, error) {
|
|
@@ -6063,4 +6445,475 @@ function fetchContentAndHydrate(next, context, identifier, priority) {
|
|
|
6063
6445
|
}]
|
|
6064
6446
|
});
|
|
6065
6447
|
}
|
|
6066
|
-
|
|
6448
|
+
|
|
6449
|
+
/**
|
|
6450
|
+
@module @ember-data/store
|
|
6451
|
+
*/
|
|
6452
|
+
/**
|
|
6453
|
+
A `ManyArray` is a `MutableArray` that represents the contents of a has-many
|
|
6454
|
+
relationship.
|
|
6455
|
+
|
|
6456
|
+
The `ManyArray` is instantiated lazily the first time the relationship is
|
|
6457
|
+
requested.
|
|
6458
|
+
|
|
6459
|
+
This class is not intended to be directly instantiated by consuming applications.
|
|
6460
|
+
|
|
6461
|
+
### Inverses
|
|
6462
|
+
|
|
6463
|
+
Often, the relationships in Ember Data applications will have
|
|
6464
|
+
an inverse. For example, imagine the following models are
|
|
6465
|
+
defined:
|
|
6466
|
+
|
|
6467
|
+
```app/models/post.js
|
|
6468
|
+
import Model, { hasMany } from '@ember-data/model';
|
|
6469
|
+
|
|
6470
|
+
export default class PostModel extends Model {
|
|
6471
|
+
@hasMany('comment') comments;
|
|
6472
|
+
}
|
|
6473
|
+
```
|
|
6474
|
+
|
|
6475
|
+
```app/models/comment.js
|
|
6476
|
+
import Model, { belongsTo } from '@ember-data/model';
|
|
6477
|
+
|
|
6478
|
+
export default class CommentModel extends Model {
|
|
6479
|
+
@belongsTo('post') post;
|
|
6480
|
+
}
|
|
6481
|
+
```
|
|
6482
|
+
|
|
6483
|
+
If you created a new instance of `Post` and added
|
|
6484
|
+
a `Comment` record to its `comments` has-many
|
|
6485
|
+
relationship, you would expect the comment's `post`
|
|
6486
|
+
property to be set to the post that contained
|
|
6487
|
+
the has-many.
|
|
6488
|
+
|
|
6489
|
+
We call the record to which a relationship belongs-to the
|
|
6490
|
+
relationship's _owner_.
|
|
6491
|
+
|
|
6492
|
+
@class ManyArray
|
|
6493
|
+
@public
|
|
6494
|
+
*/
|
|
6495
|
+
class RelatedCollection extends IdentifierArray {
|
|
6496
|
+
/**
|
|
6497
|
+
The loading state of this array
|
|
6498
|
+
@property {Boolean} isLoaded
|
|
6499
|
+
@public
|
|
6500
|
+
*/
|
|
6501
|
+
|
|
6502
|
+
/**
|
|
6503
|
+
`true` if the relationship is polymorphic, `false` otherwise.
|
|
6504
|
+
@property {Boolean} isPolymorphic
|
|
6505
|
+
@private
|
|
6506
|
+
*/
|
|
6507
|
+
|
|
6508
|
+
/**
|
|
6509
|
+
Metadata associated with the request for async hasMany relationships.
|
|
6510
|
+
Example
|
|
6511
|
+
Given that the server returns the following JSON payload when fetching a
|
|
6512
|
+
hasMany relationship:
|
|
6513
|
+
```js
|
|
6514
|
+
{
|
|
6515
|
+
"comments": [{
|
|
6516
|
+
"id": 1,
|
|
6517
|
+
"comment": "This is the first comment",
|
|
6518
|
+
}, {
|
|
6519
|
+
// ...
|
|
6520
|
+
}],
|
|
6521
|
+
"meta": {
|
|
6522
|
+
"page": 1,
|
|
6523
|
+
"total": 5
|
|
6524
|
+
}
|
|
6525
|
+
}
|
|
6526
|
+
```
|
|
6527
|
+
You can then access the meta data via the `meta` property:
|
|
6528
|
+
```js
|
|
6529
|
+
let comments = await post.comments;
|
|
6530
|
+
let meta = comments.meta;
|
|
6531
|
+
// meta.page => 1
|
|
6532
|
+
// meta.total => 5
|
|
6533
|
+
```
|
|
6534
|
+
@property {Object | null} meta
|
|
6535
|
+
@public
|
|
6536
|
+
*/
|
|
6537
|
+
|
|
6538
|
+
/**
|
|
6539
|
+
* Retrieve the links for this relationship
|
|
6540
|
+
*
|
|
6541
|
+
@property {Object | null} links
|
|
6542
|
+
@public
|
|
6543
|
+
*/
|
|
6544
|
+
|
|
6545
|
+
constructor(options) {
|
|
6546
|
+
super(options);
|
|
6547
|
+
this.isLoaded = options.isLoaded || false;
|
|
6548
|
+
this.isAsync = options.isAsync || false;
|
|
6549
|
+
this.isPolymorphic = options.isPolymorphic || false;
|
|
6550
|
+
this.identifier = options.identifier;
|
|
6551
|
+
this.key = options.key;
|
|
6552
|
+
}
|
|
6553
|
+
[MUTATE](target, receiver, prop, args, _SIGNAL) {
|
|
6554
|
+
switch (prop) {
|
|
6555
|
+
case 'length 0':
|
|
6556
|
+
{
|
|
6557
|
+
Reflect.set(target, 'length', 0);
|
|
6558
|
+
mutateReplaceRelatedRecords(this, [], _SIGNAL);
|
|
6559
|
+
return true;
|
|
6560
|
+
}
|
|
6561
|
+
case 'replace cell':
|
|
6562
|
+
{
|
|
6563
|
+
const [index, prior, value] = args;
|
|
6564
|
+
target[index] = value;
|
|
6565
|
+
mutateReplaceRelatedRecord(this, {
|
|
6566
|
+
value,
|
|
6567
|
+
prior,
|
|
6568
|
+
index
|
|
6569
|
+
}, _SIGNAL);
|
|
6570
|
+
return true;
|
|
6571
|
+
}
|
|
6572
|
+
case 'push':
|
|
6573
|
+
{
|
|
6574
|
+
const newValues = extractIdentifiersFromRecords(args);
|
|
6575
|
+
assertNoDuplicates(this, target, currentState => currentState.push(...newValues), `Cannot push duplicates to a hasMany's state.`);
|
|
6576
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6577
|
+
// dedupe
|
|
6578
|
+
const seen = new Set(target);
|
|
6579
|
+
const unique = new Set();
|
|
6580
|
+
args.forEach(item => {
|
|
6581
|
+
const identifier = recordIdentifierFor(item);
|
|
6582
|
+
if (!seen.has(identifier)) {
|
|
6583
|
+
seen.add(identifier);
|
|
6584
|
+
unique.add(item);
|
|
6585
|
+
}
|
|
6586
|
+
});
|
|
6587
|
+
const newArgs = Array.from(unique);
|
|
6588
|
+
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
6589
|
+
if (newArgs.length) {
|
|
6590
|
+
mutateAddToRelatedRecords(this, {
|
|
6591
|
+
value: extractIdentifiersFromRecords(newArgs)
|
|
6592
|
+
}, _SIGNAL);
|
|
6593
|
+
}
|
|
6594
|
+
return result;
|
|
6595
|
+
}
|
|
6596
|
+
|
|
6597
|
+
// else, no dedupe, error on duplicates
|
|
6598
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6599
|
+
if (newValues.length) {
|
|
6600
|
+
mutateAddToRelatedRecords(this, {
|
|
6601
|
+
value: newValues
|
|
6602
|
+
}, _SIGNAL);
|
|
6603
|
+
}
|
|
6604
|
+
return result;
|
|
6605
|
+
}
|
|
6606
|
+
case 'pop':
|
|
6607
|
+
{
|
|
6608
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6609
|
+
if (result) {
|
|
6610
|
+
mutateRemoveFromRelatedRecords(this, {
|
|
6611
|
+
value: recordIdentifierFor(result)
|
|
6612
|
+
}, _SIGNAL);
|
|
6613
|
+
}
|
|
6614
|
+
return result;
|
|
6615
|
+
}
|
|
6616
|
+
case 'unshift':
|
|
6617
|
+
{
|
|
6618
|
+
const newValues = extractIdentifiersFromRecords(args);
|
|
6619
|
+
assertNoDuplicates(this, target, currentState => currentState.unshift(...newValues), `Cannot unshift duplicates to a hasMany's state.`);
|
|
6620
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6621
|
+
// dedupe
|
|
6622
|
+
const seen = new Set(target);
|
|
6623
|
+
const unique = new Set();
|
|
6624
|
+
args.forEach(item => {
|
|
6625
|
+
const identifier = recordIdentifierFor(item);
|
|
6626
|
+
if (!seen.has(identifier)) {
|
|
6627
|
+
seen.add(identifier);
|
|
6628
|
+
unique.add(item);
|
|
6629
|
+
}
|
|
6630
|
+
});
|
|
6631
|
+
const newArgs = Array.from(unique);
|
|
6632
|
+
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
6633
|
+
if (newArgs.length) {
|
|
6634
|
+
mutateAddToRelatedRecords(this, {
|
|
6635
|
+
value: extractIdentifiersFromRecords(newArgs),
|
|
6636
|
+
index: 0
|
|
6637
|
+
}, _SIGNAL);
|
|
6638
|
+
}
|
|
6639
|
+
return result;
|
|
6640
|
+
}
|
|
6641
|
+
|
|
6642
|
+
// else, no dedupe, error on duplicates
|
|
6643
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6644
|
+
if (newValues.length) {
|
|
6645
|
+
mutateAddToRelatedRecords(this, {
|
|
6646
|
+
value: newValues,
|
|
6647
|
+
index: 0
|
|
6648
|
+
}, _SIGNAL);
|
|
6649
|
+
}
|
|
6650
|
+
return result;
|
|
6651
|
+
}
|
|
6652
|
+
case 'shift':
|
|
6653
|
+
{
|
|
6654
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6655
|
+
if (result) {
|
|
6656
|
+
mutateRemoveFromRelatedRecords(this, {
|
|
6657
|
+
value: recordIdentifierFor(result),
|
|
6658
|
+
index: 0
|
|
6659
|
+
}, _SIGNAL);
|
|
6660
|
+
}
|
|
6661
|
+
return result;
|
|
6662
|
+
}
|
|
6663
|
+
case 'sort':
|
|
6664
|
+
{
|
|
6665
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6666
|
+
mutateSortRelatedRecords(this, result.map(recordIdentifierFor), _SIGNAL);
|
|
6667
|
+
return result;
|
|
6668
|
+
}
|
|
6669
|
+
case 'splice':
|
|
6670
|
+
{
|
|
6671
|
+
const [start, deleteCount, ...adds] = args;
|
|
6672
|
+
|
|
6673
|
+
// detect a full replace
|
|
6674
|
+
if (start === 0 && deleteCount === this[SOURCE].length) {
|
|
6675
|
+
const newValues = extractIdentifiersFromRecords(adds);
|
|
6676
|
+
assertNoDuplicates(this, target, currentState => currentState.splice(start, deleteCount, ...newValues), `Cannot replace a hasMany's state with a new state that contains duplicates.`);
|
|
6677
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6678
|
+
// dedupe
|
|
6679
|
+
const current = new Set(adds);
|
|
6680
|
+
const unique = Array.from(current);
|
|
6681
|
+
const newArgs = [start, deleteCount].concat(unique);
|
|
6682
|
+
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
6683
|
+
mutateReplaceRelatedRecords(this, extractIdentifiersFromRecords(unique), _SIGNAL);
|
|
6684
|
+
return result;
|
|
6685
|
+
}
|
|
6686
|
+
|
|
6687
|
+
// else, no dedupe, error on duplicates
|
|
6688
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6689
|
+
mutateReplaceRelatedRecords(this, newValues, _SIGNAL);
|
|
6690
|
+
return result;
|
|
6691
|
+
}
|
|
6692
|
+
const newValues = extractIdentifiersFromRecords(adds);
|
|
6693
|
+
assertNoDuplicates(this, target, currentState => currentState.splice(start, deleteCount, ...newValues), `Cannot splice a hasMany's state with a new state that contains duplicates.`);
|
|
6694
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6695
|
+
// dedupe
|
|
6696
|
+
const currentState = target.slice();
|
|
6697
|
+
currentState.splice(start, deleteCount);
|
|
6698
|
+
const seen = new Set(currentState);
|
|
6699
|
+
const unique = [];
|
|
6700
|
+
adds.forEach(item => {
|
|
6701
|
+
const identifier = recordIdentifierFor(item);
|
|
6702
|
+
if (!seen.has(identifier)) {
|
|
6703
|
+
seen.add(identifier);
|
|
6704
|
+
unique.push(item);
|
|
6705
|
+
}
|
|
6706
|
+
});
|
|
6707
|
+
const newArgs = [start, deleteCount, ...unique];
|
|
6708
|
+
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
6709
|
+
if (deleteCount > 0) {
|
|
6710
|
+
mutateRemoveFromRelatedRecords(this, {
|
|
6711
|
+
value: result.map(recordIdentifierFor),
|
|
6712
|
+
index: start
|
|
6713
|
+
}, _SIGNAL);
|
|
6714
|
+
}
|
|
6715
|
+
if (unique.length > 0) {
|
|
6716
|
+
mutateAddToRelatedRecords(this, {
|
|
6717
|
+
value: extractIdentifiersFromRecords(unique),
|
|
6718
|
+
index: start
|
|
6719
|
+
}, _SIGNAL);
|
|
6720
|
+
}
|
|
6721
|
+
return result;
|
|
6722
|
+
}
|
|
6723
|
+
|
|
6724
|
+
// else, no dedupe, error on duplicates
|
|
6725
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6726
|
+
if (deleteCount > 0) {
|
|
6727
|
+
mutateRemoveFromRelatedRecords(this, {
|
|
6728
|
+
value: result.map(recordIdentifierFor),
|
|
6729
|
+
index: start
|
|
6730
|
+
}, _SIGNAL);
|
|
6731
|
+
}
|
|
6732
|
+
if (newValues.length > 0) {
|
|
6733
|
+
mutateAddToRelatedRecords(this, {
|
|
6734
|
+
value: newValues,
|
|
6735
|
+
index: start
|
|
6736
|
+
}, _SIGNAL);
|
|
6737
|
+
}
|
|
6738
|
+
return result;
|
|
6739
|
+
}
|
|
6740
|
+
default:
|
|
6741
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6742
|
+
{
|
|
6743
|
+
throw new Error(`unable to convert ${prop} into a transaction that updates the cache state for this record array`);
|
|
6744
|
+
}
|
|
6745
|
+
})() : {};
|
|
6746
|
+
}
|
|
6747
|
+
}
|
|
6748
|
+
notify() {
|
|
6749
|
+
const signal = this[ARRAY_SIGNAL];
|
|
6750
|
+
signal.shouldReset = true;
|
|
6751
|
+
notifyArray(this);
|
|
6752
|
+
}
|
|
6753
|
+
|
|
6754
|
+
/**
|
|
6755
|
+
Reloads all of the records in the manyArray. If the manyArray
|
|
6756
|
+
holds a relationship that was originally fetched using a links url
|
|
6757
|
+
EmberData will revisit the original links url to repopulate the
|
|
6758
|
+
relationship.
|
|
6759
|
+
If the ManyArray holds the result of a `store.query()` reload will
|
|
6760
|
+
re-run the original query.
|
|
6761
|
+
Example
|
|
6762
|
+
```javascript
|
|
6763
|
+
let user = store.peekRecord('user', '1')
|
|
6764
|
+
await login(user);
|
|
6765
|
+
let permissions = await user.permissions;
|
|
6766
|
+
await permissions.reload();
|
|
6767
|
+
```
|
|
6768
|
+
@method reload
|
|
6769
|
+
@public
|
|
6770
|
+
*/
|
|
6771
|
+
reload(options) {
|
|
6772
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6773
|
+
if (!test) {
|
|
6774
|
+
throw new Error(`Expected the manager for ManyArray to implement reloadHasMany`);
|
|
6775
|
+
}
|
|
6776
|
+
})(typeof this._manager.reloadHasMany === 'function') : {};
|
|
6777
|
+
// TODO this is odd, we don't ask the store for anything else like this?
|
|
6778
|
+
return this._manager.reloadHasMany(this.key, options);
|
|
6779
|
+
}
|
|
6780
|
+
|
|
6781
|
+
/**
|
|
6782
|
+
Saves all of the records in the `ManyArray`.
|
|
6783
|
+
Note: this API can only be used in legacy mode with a configured Adapter.
|
|
6784
|
+
Example
|
|
6785
|
+
```javascript
|
|
6786
|
+
const { content: { data: inbox } } = await store.request(findRecord({ type: 'inbox', id: '1' }));
|
|
6787
|
+
let messages = await inbox.messages;
|
|
6788
|
+
messages.forEach((message) => {
|
|
6789
|
+
message.isRead = true;
|
|
6790
|
+
});
|
|
6791
|
+
messages.save();
|
|
6792
|
+
```
|
|
6793
|
+
@method save
|
|
6794
|
+
@public
|
|
6795
|
+
@return {PromiseArray} promise
|
|
6796
|
+
*/
|
|
6797
|
+
|
|
6798
|
+
/**
|
|
6799
|
+
Create a child record within the owner
|
|
6800
|
+
@method createRecord
|
|
6801
|
+
@public
|
|
6802
|
+
@param {Object} hash
|
|
6803
|
+
@return {Model} record
|
|
6804
|
+
*/
|
|
6805
|
+
createRecord(hash) {
|
|
6806
|
+
const {
|
|
6807
|
+
store
|
|
6808
|
+
} = this;
|
|
6809
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6810
|
+
if (!test) {
|
|
6811
|
+
throw new Error(`Expected modelName to be set`);
|
|
6812
|
+
}
|
|
6813
|
+
})(this.modelName) : {};
|
|
6814
|
+
const record = store.createRecord(this.modelName, hash);
|
|
6815
|
+
this.push(record);
|
|
6816
|
+
return record;
|
|
6817
|
+
}
|
|
6818
|
+
destroy() {
|
|
6819
|
+
super.destroy(false);
|
|
6820
|
+
}
|
|
6821
|
+
}
|
|
6822
|
+
RelatedCollection.prototype.isAsync = false;
|
|
6823
|
+
RelatedCollection.prototype.isPolymorphic = false;
|
|
6824
|
+
RelatedCollection.prototype.identifier = null;
|
|
6825
|
+
RelatedCollection.prototype.cache = null;
|
|
6826
|
+
RelatedCollection.prototype._inverseIsAsync = false;
|
|
6827
|
+
RelatedCollection.prototype.key = '';
|
|
6828
|
+
RelatedCollection.prototype.DEPRECATED_CLASS_NAME = 'ManyArray';
|
|
6829
|
+
function assertRecordPassedToHasMany(record) {
|
|
6830
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6831
|
+
if (!test) {
|
|
6832
|
+
throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed ${typeof record}`);
|
|
6833
|
+
}
|
|
6834
|
+
})(function () {
|
|
6835
|
+
try {
|
|
6836
|
+
recordIdentifierFor(record);
|
|
6837
|
+
return true;
|
|
6838
|
+
} catch {
|
|
6839
|
+
return false;
|
|
6840
|
+
}
|
|
6841
|
+
}()) : {};
|
|
6842
|
+
}
|
|
6843
|
+
function extractIdentifiersFromRecords(records) {
|
|
6844
|
+
return records.map(extractIdentifierFromRecord);
|
|
6845
|
+
}
|
|
6846
|
+
function extractIdentifierFromRecord(recordOrPromiseRecord) {
|
|
6847
|
+
assertRecordPassedToHasMany(recordOrPromiseRecord);
|
|
6848
|
+
return recordIdentifierFor(recordOrPromiseRecord);
|
|
6849
|
+
}
|
|
6850
|
+
function assertNoDuplicates(collection, target, callback, reason) {
|
|
6851
|
+
const state = target.slice();
|
|
6852
|
+
callback(state);
|
|
6853
|
+
if (state.length !== new Set(state).size) {
|
|
6854
|
+
const duplicates = state.filter((currentValue, currentIndex) => state.indexOf(currentValue) !== currentIndex);
|
|
6855
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6856
|
+
deprecate(`${reason} This behavior is deprecated. Found duplicates for the following records within the new state provided to \`<${collection.identifier.type}:${collection.identifier.id || collection.identifier.lid}>.${collection.key}\`\n\t- ${Array.from(new Set(duplicates)).map(r => isStableIdentifier(r) ? r.lid : recordIdentifierFor(r).lid).sort((a, b) => a.localeCompare(b)).join('\n\t- ')}`, false, {
|
|
6857
|
+
id: 'ember-data:deprecate-many-array-duplicates',
|
|
6858
|
+
for: 'ember-data',
|
|
6859
|
+
until: '6.0',
|
|
6860
|
+
since: {
|
|
6861
|
+
enabled: '5.3',
|
|
6862
|
+
available: '4.13'
|
|
6863
|
+
}
|
|
6864
|
+
});
|
|
6865
|
+
} else {
|
|
6866
|
+
throw new Error(`${reason} Found duplicates for the following records within the new state provided to \`<${collection.identifier.type}:${collection.identifier.id || collection.identifier.lid}>.${collection.key}\`\n\t- ${Array.from(new Set(duplicates)).map(r => isStableIdentifier(r) ? r.lid : recordIdentifierFor(r).lid).sort((a, b) => a.localeCompare(b)).join('\n\t- ')}`);
|
|
6867
|
+
}
|
|
6868
|
+
}
|
|
6869
|
+
}
|
|
6870
|
+
function mutateAddToRelatedRecords(collection, operationInfo, _SIGNAL) {
|
|
6871
|
+
mutate(collection, {
|
|
6872
|
+
op: 'add',
|
|
6873
|
+
record: collection.identifier,
|
|
6874
|
+
field: collection.key,
|
|
6875
|
+
...operationInfo
|
|
6876
|
+
}, _SIGNAL);
|
|
6877
|
+
}
|
|
6878
|
+
function mutateRemoveFromRelatedRecords(collection, operationInfo, _SIGNAL) {
|
|
6879
|
+
mutate(collection, {
|
|
6880
|
+
op: 'remove',
|
|
6881
|
+
record: collection.identifier,
|
|
6882
|
+
field: collection.key,
|
|
6883
|
+
...operationInfo
|
|
6884
|
+
}, _SIGNAL);
|
|
6885
|
+
}
|
|
6886
|
+
function mutateReplaceRelatedRecord(collection, operationInfo, _SIGNAL) {
|
|
6887
|
+
mutate(collection, {
|
|
6888
|
+
op: 'replaceRelatedRecord',
|
|
6889
|
+
record: collection.identifier,
|
|
6890
|
+
field: collection.key,
|
|
6891
|
+
...operationInfo
|
|
6892
|
+
}, _SIGNAL);
|
|
6893
|
+
}
|
|
6894
|
+
function mutateReplaceRelatedRecords(collection, value, _SIGNAL) {
|
|
6895
|
+
mutate(collection, {
|
|
6896
|
+
op: 'replaceRelatedRecords',
|
|
6897
|
+
record: collection.identifier,
|
|
6898
|
+
field: collection.key,
|
|
6899
|
+
value
|
|
6900
|
+
}, _SIGNAL);
|
|
6901
|
+
}
|
|
6902
|
+
function mutateSortRelatedRecords(collection, value, _SIGNAL) {
|
|
6903
|
+
mutate(collection, {
|
|
6904
|
+
op: 'sortRelatedRecords',
|
|
6905
|
+
record: collection.identifier,
|
|
6906
|
+
field: collection.key,
|
|
6907
|
+
value
|
|
6908
|
+
}, _SIGNAL);
|
|
6909
|
+
}
|
|
6910
|
+
function mutate(collection, mutation, _SIGNAL) {
|
|
6911
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6912
|
+
if (!test) {
|
|
6913
|
+
throw new Error(`Expected the manager for ManyArray to implement mutate`);
|
|
6914
|
+
}
|
|
6915
|
+
})(typeof collection._manager.mutate === 'function') : {};
|
|
6916
|
+
collection._manager.mutate(mutation);
|
|
6917
|
+
addToTransaction(_SIGNAL);
|
|
6918
|
+
}
|
|
6919
|
+
export { ARRAY_SIGNAL as A, CacheHandler as C, IdentifierArray as I, MUTATE as M, RecordArrayManager as R, Store as S, _clearCaches as _, setIdentifierGenerationMethod as a, setIdentifierUpdateMethod as b, setIdentifierForgetMethod as c, setIdentifierResetMethod as d, setKeyInfoForResource as e, isDocumentIdentifier as f, constructResource as g, coerceId as h, isStableIdentifier as i, ensureStringId as j, Collection as k, SOURCE as l, fastPush as m, notifyArray as n, removeRecordDataFor as o, peekCache as p, setRecordIdentifier as q, recordIdentifierFor as r, storeFor as s, StoreMap as t, setCacheFor as u, normalizeModelName as v, RelatedCollection as w, log as x, logGroup as y };
|