@ember-data/store 5.4.0-beta.14 → 5.4.0-beta.16
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 +5 -8
- package/dist/-private.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{handler-CW2kp6Ua.js → many-array-V2cR1muR.js} +935 -153
- package/dist/many-array-V2cR1muR.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 +24 -43
- package/unstable-preview-types/-private/cache-handler/handler.d.ts +0 -2
- package/unstable-preview-types/-private/cache-handler/handler.d.ts.map +1 -1
- package/unstable-preview-types/-private/caches/identifier-cache.d.ts.map +1 -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/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 +2 -0
- 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 +11 -1
- 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 +64 -9
- package/unstable-preview-types/-private/store-service.d.ts.map +1 -1
- package/unstable-preview-types/-private.d.ts +2 -0
- 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/schema-service.d.ts +4 -4
- package/unstable-preview-types/-types/q/schema-service.d.ts.map +1 -1
- package/unstable-preview-types/index.d.ts +24 -25
- package/unstable-preview-types/index.d.ts.map +1 -1
- package/dist/handler-CW2kp6Ua.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
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { setLogging, getRuntimeConfig } from '@warp-drive/build-config/runtime';
|
|
4
|
+
import { EnableHydration, SkipCache } from '@warp-drive/core-types/request';
|
|
5
|
+
import { getOrSetGlobal, peekTransient, setTransient } from '@warp-drive/core-types/-private';
|
|
6
|
+
import { _backburner } from '@ember/runloop';
|
|
7
|
+
import { defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
|
|
5
8
|
import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_CLIENT_ORIGINATED, DEBUG_IDENTIFIER_BUCKET } from '@warp-drive/core-types/identifier';
|
|
6
9
|
import { dasherize } from '@ember-data/request-utils/string';
|
|
7
|
-
import { defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
|
|
8
|
-
import { _backburner } from '@ember/runloop';
|
|
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,7 +658,6 @@ 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
|
|
@@ -692,7 +712,6 @@ function makeStableRecordIdentifier(recordIdentifier, bucket, clientOriginated)
|
|
|
692
712
|
});
|
|
693
713
|
wrapper[DEBUG_CLIENT_ORIGINATED] = clientOriginated;
|
|
694
714
|
wrapper[DEBUG_IDENTIFIER_BUCKET] = bucket;
|
|
695
|
-
IDENTIFIERS.add(wrapper);
|
|
696
715
|
DEBUG_MAP.set(wrapper, recordIdentifier);
|
|
697
716
|
wrapper = freeze(wrapper);
|
|
698
717
|
return wrapper;
|
|
@@ -775,9 +794,11 @@ function detectMerge(cache, keyInfo, identifier, data) {
|
|
|
775
794
|
}
|
|
776
795
|
function getIdentifierFromLid(cache, lid, resource) {
|
|
777
796
|
const identifier = cache.resources.get(lid);
|
|
778
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
779
|
-
|
|
780
|
-
|
|
797
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_IDENTIFIERS)) {
|
|
798
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_IDENTIFIERS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_IDENTIFIERS) {
|
|
799
|
+
// eslint-disable-next-line no-console
|
|
800
|
+
console.log(`Identifiers: cache ${identifier ? 'HIT' : 'MISS'} - Non-Stable ${lid}`, resource);
|
|
801
|
+
}
|
|
781
802
|
}
|
|
782
803
|
return identifier || null;
|
|
783
804
|
}
|
|
@@ -796,6 +817,87 @@ function addResourceToCache(cache, identifier) {
|
|
|
796
817
|
typeSet.id.set(identifier.id, identifier);
|
|
797
818
|
}
|
|
798
819
|
}
|
|
820
|
+
const TEXT_COLORS = {
|
|
821
|
+
TEXT: 'inherit',
|
|
822
|
+
notify: ['white', 'white', 'inherit', 'magenta', 'inherit'],
|
|
823
|
+
'reactive-ui': ['white', 'white', 'inherit', 'magenta', 'inherit'],
|
|
824
|
+
graph: ['white', 'white', 'inherit', 'magenta', 'inherit'],
|
|
825
|
+
request: ['white', 'white', 'inherit', 'magenta', 'inherit'],
|
|
826
|
+
cache: ['white', 'white', 'inherit', 'magenta', 'inherit']
|
|
827
|
+
};
|
|
828
|
+
const BG_COLORS = {
|
|
829
|
+
TEXT: 'transparent',
|
|
830
|
+
notify: ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent'],
|
|
831
|
+
'reactive-ui': ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent'],
|
|
832
|
+
graph: ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent'],
|
|
833
|
+
request: ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent'],
|
|
834
|
+
cache: ['dimgray', 'cadetblue', 'transparent', 'transparent', 'transparent']
|
|
835
|
+
};
|
|
836
|
+
const NOTIFY_BORDER = {
|
|
837
|
+
TEXT: 0,
|
|
838
|
+
notify: [3, 2, 0, 0, 0],
|
|
839
|
+
'reactive-ui': [3, 2, 0, 0, 0],
|
|
840
|
+
graph: [3, 2, 0, 0, 0],
|
|
841
|
+
request: [3, 2, 0, 0, 0],
|
|
842
|
+
cache: [3, 2, 0, 0, 0]
|
|
843
|
+
};
|
|
844
|
+
const LIGHT_DARK_ALT = {
|
|
845
|
+
lightgreen: 'green',
|
|
846
|
+
green: 'lightgreen'
|
|
847
|
+
};
|
|
848
|
+
function badge(isLight, color, bgColor, border) {
|
|
849
|
+
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};`];
|
|
850
|
+
}
|
|
851
|
+
function colorForBucket(isLight, scope, bucket) {
|
|
852
|
+
if (scope === 'notify') {
|
|
853
|
+
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]);
|
|
854
|
+
}
|
|
855
|
+
if (scope === 'reactive-ui') {
|
|
856
|
+
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]);
|
|
857
|
+
}
|
|
858
|
+
if (scope === 'cache') {
|
|
859
|
+
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]);
|
|
860
|
+
}
|
|
861
|
+
return badge(isLight, TEXT_COLORS[scope][3], BG_COLORS[scope][3], NOTIFY_BORDER[scope][3]);
|
|
862
|
+
}
|
|
863
|
+
function logGroup(scope, prefix, subScop1, subScop2, subScop3, subScop4) {
|
|
864
|
+
// eslint-disable-next-line no-console
|
|
865
|
+
console.groupCollapsed(..._log(scope, prefix, subScop1, subScop2, subScop3, subScop4));
|
|
866
|
+
}
|
|
867
|
+
function log(scope, prefix, subScop1, subScop2, subScop3, subScop4) {
|
|
868
|
+
// eslint-disable-next-line no-console
|
|
869
|
+
console.log(..._log(scope, prefix, subScop1, subScop2, subScop3, subScop4));
|
|
870
|
+
}
|
|
871
|
+
function correctColor(isLight, color) {
|
|
872
|
+
if (!isLight) {
|
|
873
|
+
return color;
|
|
874
|
+
}
|
|
875
|
+
return color in LIGHT_DARK_ALT ? LIGHT_DARK_ALT[color] : color;
|
|
876
|
+
}
|
|
877
|
+
function isLightMode() {
|
|
878
|
+
if (window?.matchMedia?.('(prefers-color-scheme: light)').matches) {
|
|
879
|
+
return true;
|
|
880
|
+
}
|
|
881
|
+
return false;
|
|
882
|
+
}
|
|
883
|
+
function _log(scope, prefix, subScop1, subScop2, subScop3, subScop4) {
|
|
884
|
+
const isLight = isLightMode();
|
|
885
|
+
switch (scope) {
|
|
886
|
+
case 'reactive-ui':
|
|
887
|
+
case 'notify':
|
|
888
|
+
{
|
|
889
|
+
const scopePath = prefix ? `[${prefix}] ${scope}` : scope;
|
|
890
|
+
const path = subScop4 ? `${subScop3}.${subScop4}` : subScop3;
|
|
891
|
+
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)];
|
|
892
|
+
}
|
|
893
|
+
case 'cache':
|
|
894
|
+
{
|
|
895
|
+
const scopePath = prefix ? `${scope} (${prefix})` : scope;
|
|
896
|
+
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])];
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
return [];
|
|
900
|
+
}
|
|
799
901
|
|
|
800
902
|
/**
|
|
801
903
|
@module @ember-data/store
|
|
@@ -1252,9 +1354,16 @@ class InstanceCache {
|
|
|
1252
1354
|
setCacheFor(record, cache);
|
|
1253
1355
|
StoreMap.set(record, this.store);
|
|
1254
1356
|
this.__instances.record.set(identifier, record);
|
|
1255
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1256
|
-
|
|
1257
|
-
|
|
1357
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1358
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1359
|
+
logGroup('reactive-ui', '', identifier.type, identifier.lid, 'created', '');
|
|
1360
|
+
// eslint-disable-next-line no-console
|
|
1361
|
+
console.log({
|
|
1362
|
+
properties
|
|
1363
|
+
});
|
|
1364
|
+
// eslint-disable-next-line no-console
|
|
1365
|
+
console.groupEnd();
|
|
1366
|
+
}
|
|
1258
1367
|
}
|
|
1259
1368
|
}
|
|
1260
1369
|
return record;
|
|
@@ -1300,9 +1409,10 @@ class InstanceCache {
|
|
|
1300
1409
|
this.store.identifierCache.forgetRecordIdentifier(identifier);
|
|
1301
1410
|
removeRecordDataFor(identifier);
|
|
1302
1411
|
this.store._requestCache._clearEntries(identifier);
|
|
1303
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1304
|
-
|
|
1305
|
-
|
|
1412
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1413
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1414
|
+
log('reactive-ui', '', identifier.type, identifier.lid, 'disconnected', '');
|
|
1415
|
+
}
|
|
1306
1416
|
}
|
|
1307
1417
|
}
|
|
1308
1418
|
unloadRecord(identifier) {
|
|
@@ -1318,9 +1428,11 @@ class InstanceCache {
|
|
|
1318
1428
|
})() : {};
|
|
1319
1429
|
}
|
|
1320
1430
|
}
|
|
1321
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1322
|
-
|
|
1323
|
-
|
|
1431
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1432
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1433
|
+
// eslint-disable-next-line no-console
|
|
1434
|
+
console.groupCollapsed(`InstanceCache: unloading record for ${String(identifier)}`);
|
|
1435
|
+
}
|
|
1324
1436
|
}
|
|
1325
1437
|
|
|
1326
1438
|
// TODO is this join still necessary?
|
|
@@ -1333,27 +1445,33 @@ class InstanceCache {
|
|
|
1333
1445
|
StoreMap.delete(record);
|
|
1334
1446
|
RecordCache.delete(record);
|
|
1335
1447
|
removeRecordDataFor(record);
|
|
1336
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1337
|
-
|
|
1338
|
-
|
|
1448
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1449
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1450
|
+
// eslint-disable-next-line no-console
|
|
1451
|
+
console.log(`InstanceCache: destroyed record for ${String(identifier)}`);
|
|
1452
|
+
}
|
|
1339
1453
|
}
|
|
1340
1454
|
}
|
|
1341
1455
|
if (cache) {
|
|
1342
1456
|
cache.unloadRecord(identifier);
|
|
1343
1457
|
removeRecordDataFor(identifier);
|
|
1344
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1345
|
-
|
|
1346
|
-
|
|
1458
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1459
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1460
|
+
// eslint-disable-next-line no-console
|
|
1461
|
+
console.log(`InstanceCache: destroyed cache for ${String(identifier)}`);
|
|
1462
|
+
}
|
|
1347
1463
|
}
|
|
1348
1464
|
} else {
|
|
1349
1465
|
this.disconnect(identifier);
|
|
1350
1466
|
}
|
|
1351
1467
|
this.store._requestCache._clearEntries(identifier);
|
|
1352
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1468
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1469
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1470
|
+
// eslint-disable-next-line no-console
|
|
1471
|
+
console.log(`InstanceCache: unloaded RecordData for ${String(identifier)}`);
|
|
1472
|
+
// eslint-disable-next-line no-console
|
|
1473
|
+
console.groupEnd();
|
|
1474
|
+
}
|
|
1357
1475
|
}
|
|
1358
1476
|
});
|
|
1359
1477
|
}
|
|
@@ -1408,9 +1526,11 @@ class InstanceCache {
|
|
|
1408
1526
|
warn(`Your ${type} record was saved to the server, but the response does not have an id.`, !(oldId !== null && id === null));
|
|
1409
1527
|
return;
|
|
1410
1528
|
}
|
|
1411
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
1412
|
-
|
|
1413
|
-
|
|
1529
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
|
|
1530
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
|
|
1531
|
+
// eslint-disable-next-line no-console
|
|
1532
|
+
console.log(`InstanceCache: updating id to '${id}' for record ${String(identifier)}`);
|
|
1533
|
+
}
|
|
1414
1534
|
}
|
|
1415
1535
|
const existingIdentifier = this.store.identifierCache.peekRecordIdentifier({
|
|
1416
1536
|
type,
|
|
@@ -1727,7 +1847,9 @@ class CacheManager {
|
|
|
1727
1847
|
peek(identifier) {
|
|
1728
1848
|
return this.#cache.peek(identifier);
|
|
1729
1849
|
}
|
|
1730
|
-
|
|
1850
|
+
peekRemoteState(identifier) {
|
|
1851
|
+
return this.#cache.peekRemoteState(identifier);
|
|
1852
|
+
}
|
|
1731
1853
|
/**
|
|
1732
1854
|
* Peek the Cache for the existing request data associated with
|
|
1733
1855
|
* a cacheable request
|
|
@@ -1950,6 +2072,19 @@ class CacheManager {
|
|
|
1950
2072
|
return this.#cache.getAttr(identifier, propertyName);
|
|
1951
2073
|
}
|
|
1952
2074
|
|
|
2075
|
+
/**
|
|
2076
|
+
* Retrieve the remote state for an attribute from the cache
|
|
2077
|
+
*
|
|
2078
|
+
* @method getRemoteAttr
|
|
2079
|
+
* @public
|
|
2080
|
+
* @param identifier
|
|
2081
|
+
* @param propertyName
|
|
2082
|
+
* @return {unknown}
|
|
2083
|
+
*/
|
|
2084
|
+
getRemoteAttr(identifier, propertyName) {
|
|
2085
|
+
return this.#cache.getRemoteAttr(identifier, propertyName);
|
|
2086
|
+
}
|
|
2087
|
+
|
|
1953
2088
|
/**
|
|
1954
2089
|
* Mutate the data for an attribute in the cache
|
|
1955
2090
|
*
|
|
@@ -2074,6 +2209,19 @@ class CacheManager {
|
|
|
2074
2209
|
return this.#cache.getRelationship(identifier, propertyName);
|
|
2075
2210
|
}
|
|
2076
2211
|
|
|
2212
|
+
/**
|
|
2213
|
+
* Query the cache for the remote state of a relationship property
|
|
2214
|
+
*
|
|
2215
|
+
* @method getRelationship
|
|
2216
|
+
* @public
|
|
2217
|
+
* @param identifier
|
|
2218
|
+
* @param propertyName
|
|
2219
|
+
* @return resource relationship object
|
|
2220
|
+
*/
|
|
2221
|
+
getRemoteRelationship(identifier, propertyName) {
|
|
2222
|
+
return this.#cache.getRemoteRelationship(identifier, propertyName);
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2077
2225
|
// Resource State
|
|
2078
2226
|
// ===============
|
|
2079
2227
|
|
|
@@ -2158,27 +2306,51 @@ class CacheManager {
|
|
|
2158
2306
|
* @module @ember-data/store
|
|
2159
2307
|
*/
|
|
2160
2308
|
|
|
2161
|
-
let tokenId = 0;
|
|
2162
|
-
const CacheOperations = new Set(['added', 'removed', 'state', 'updated', 'invalidated']);
|
|
2163
2309
|
function isCacheOperationValue(value) {
|
|
2164
|
-
return
|
|
2310
|
+
return value === 'added' || value === 'state' || value === 'updated' || value === 'removed' || value === 'invalidated';
|
|
2165
2311
|
}
|
|
2166
2312
|
function runLoopIsFlushing() {
|
|
2167
2313
|
//@ts-expect-error
|
|
2168
2314
|
return !!_backburner.currentInstance && _backburner._autorun !== true;
|
|
2169
2315
|
}
|
|
2170
|
-
function
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2316
|
+
function count(label) {
|
|
2317
|
+
// @ts-expect-error
|
|
2318
|
+
// eslint-disable-next-line
|
|
2319
|
+
globalThis.__WarpDriveMetricCountData[label] = (globalThis.__WarpDriveMetricCountData[label] || 0) + 1;
|
|
2320
|
+
}
|
|
2321
|
+
function asInternalToken(token) {
|
|
2322
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2323
|
+
if (!test) {
|
|
2324
|
+
throw new Error(`Expected a token with a 'for' property`);
|
|
2325
|
+
}
|
|
2326
|
+
})(token && typeof token === 'function' && 'for' in token) : {};
|
|
2327
|
+
}
|
|
2328
|
+
function _unsubscribe(token, cache) {
|
|
2329
|
+
asInternalToken(token);
|
|
2330
|
+
const identifier = token.for;
|
|
2331
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2332
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2333
|
+
if (!identifier) {
|
|
2334
|
+
// eslint-disable-next-line no-console
|
|
2335
|
+
console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
|
|
2336
|
+
}
|
|
2176
2337
|
}
|
|
2177
2338
|
}
|
|
2178
2339
|
if (identifier) {
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2340
|
+
const callbacks = cache.get(identifier);
|
|
2341
|
+
if (!callbacks) {
|
|
2342
|
+
return;
|
|
2343
|
+
}
|
|
2344
|
+
const index = callbacks.indexOf(token);
|
|
2345
|
+
if (index === -1) {
|
|
2346
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2347
|
+
if (!test) {
|
|
2348
|
+
throw new Error(`Cannot unsubscribe a token that is not subscribed`);
|
|
2349
|
+
}
|
|
2350
|
+
})(index !== -1) : {};
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
callbacks.splice(index, 1);
|
|
2182
2354
|
}
|
|
2183
2355
|
}
|
|
2184
2356
|
|
|
@@ -2199,7 +2371,6 @@ class NotificationManager {
|
|
|
2199
2371
|
this._buffered = new Map();
|
|
2200
2372
|
this._hasFlush = false;
|
|
2201
2373
|
this._cache = new Map();
|
|
2202
|
-
this._tokens = new Map();
|
|
2203
2374
|
}
|
|
2204
2375
|
|
|
2205
2376
|
/**
|
|
@@ -2236,17 +2407,26 @@ class NotificationManager {
|
|
|
2236
2407
|
throw new Error(`Expected to receive a stable Identifier to subscribe to`);
|
|
2237
2408
|
}
|
|
2238
2409
|
})(identifier === 'resource' || identifier === 'document' || isStableIdentifier(identifier) || isDocumentIdentifier(identifier)) : {};
|
|
2239
|
-
let
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2410
|
+
let callbacks = this._cache.get(identifier);
|
|
2411
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2412
|
+
if (!test) {
|
|
2413
|
+
throw new Error(`expected to receive a valid callback`);
|
|
2414
|
+
}
|
|
2415
|
+
})(typeof callback === 'function') : {};
|
|
2416
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2417
|
+
if (!test) {
|
|
2418
|
+
throw new Error(`cannot subscribe with the same callback twice`);
|
|
2419
|
+
}
|
|
2420
|
+
})(!callbacks || !callbacks.includes(callback)) : {};
|
|
2421
|
+
// we use the callback as the cancellation token
|
|
2422
|
+
//@ts-expect-error
|
|
2423
|
+
callback.for = identifier;
|
|
2424
|
+
if (!callbacks) {
|
|
2425
|
+
callbacks = [];
|
|
2426
|
+
this._cache.set(identifier, callbacks);
|
|
2243
2427
|
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
} : {};
|
|
2247
|
-
map.set(unsubToken, callback);
|
|
2248
|
-
this._tokens.set(unsubToken, identifier);
|
|
2249
|
-
return unsubToken;
|
|
2428
|
+
callbacks.push(callback);
|
|
2429
|
+
return callback;
|
|
2250
2430
|
}
|
|
2251
2431
|
|
|
2252
2432
|
/**
|
|
@@ -2258,7 +2438,7 @@ class NotificationManager {
|
|
|
2258
2438
|
*/
|
|
2259
2439
|
unsubscribe(token) {
|
|
2260
2440
|
if (!this.isDestroyed) {
|
|
2261
|
-
_unsubscribe(
|
|
2441
|
+
_unsubscribe(token, this._cache);
|
|
2262
2442
|
}
|
|
2263
2443
|
}
|
|
2264
2444
|
|
|
@@ -2280,17 +2460,15 @@ class NotificationManager {
|
|
|
2280
2460
|
}
|
|
2281
2461
|
})(!key || value === 'attributes' || value === 'relationships') : {};
|
|
2282
2462
|
if (!isStableIdentifier(identifier) && !isDocumentIdentifier(identifier)) {
|
|
2283
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
2284
|
-
|
|
2285
|
-
|
|
2463
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2464
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2465
|
+
// eslint-disable-next-line no-console
|
|
2466
|
+
console.log(`Notifying: Expected to receive a stable Identifier to notify '${value}' '${key || ''}' with, but ${String(identifier)} is not in the cache`, identifier);
|
|
2467
|
+
}
|
|
2286
2468
|
}
|
|
2287
2469
|
return false;
|
|
2288
2470
|
}
|
|
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);
|
|
2471
|
+
const hasSubscribers = Boolean(this._cache.get(identifier)?.length);
|
|
2294
2472
|
if (isCacheOperationValue(value) || hasSubscribers) {
|
|
2295
2473
|
let buffer = this._buffered.get(identifier);
|
|
2296
2474
|
if (!buffer) {
|
|
@@ -2298,7 +2476,22 @@ class NotificationManager {
|
|
|
2298
2476
|
this._buffered.set(identifier, buffer);
|
|
2299
2477
|
}
|
|
2300
2478
|
buffer.push([value, key]);
|
|
2301
|
-
|
|
2479
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
|
|
2480
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
|
|
2481
|
+
count(`notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
if (!this._scheduleNotify()) {
|
|
2485
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2486
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2487
|
+
log('notify', 'buffered', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
} else if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
|
|
2492
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
|
|
2493
|
+
count(`DISCARDED notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
|
|
2494
|
+
}
|
|
2302
2495
|
}
|
|
2303
2496
|
return hasSubscribers;
|
|
2304
2497
|
}
|
|
@@ -2309,14 +2502,15 @@ class NotificationManager {
|
|
|
2309
2502
|
const asyncFlush = this.store._enableAsyncFlush;
|
|
2310
2503
|
if (this._hasFlush) {
|
|
2311
2504
|
if (asyncFlush !== false && !runLoopIsFlushing()) {
|
|
2312
|
-
return;
|
|
2505
|
+
return false;
|
|
2313
2506
|
}
|
|
2314
2507
|
}
|
|
2315
2508
|
if (asyncFlush && !runLoopIsFlushing()) {
|
|
2316
2509
|
this._hasFlush = true;
|
|
2317
|
-
return;
|
|
2510
|
+
return false;
|
|
2318
2511
|
}
|
|
2319
2512
|
this._flush();
|
|
2513
|
+
return true;
|
|
2320
2514
|
}
|
|
2321
2515
|
_flush() {
|
|
2322
2516
|
const buffered = this._buffered;
|
|
@@ -2334,9 +2528,10 @@ class NotificationManager {
|
|
|
2334
2528
|
this._onFlushCB = undefined;
|
|
2335
2529
|
}
|
|
2336
2530
|
_flushNotification(identifier, value, key) {
|
|
2337
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
2338
|
-
|
|
2339
|
-
|
|
2531
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
|
|
2532
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
|
|
2533
|
+
log('notify', '', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
|
|
2534
|
+
}
|
|
2340
2535
|
}
|
|
2341
2536
|
|
|
2342
2537
|
// TODO for documents this will need to switch based on Identifier kind
|
|
@@ -2348,11 +2543,11 @@ class NotificationManager {
|
|
|
2348
2543
|
});
|
|
2349
2544
|
}
|
|
2350
2545
|
}
|
|
2351
|
-
const
|
|
2352
|
-
if (!
|
|
2546
|
+
const callbacks = this._cache.get(identifier);
|
|
2547
|
+
if (!callbacks || !callbacks.length) {
|
|
2353
2548
|
return false;
|
|
2354
2549
|
}
|
|
2355
|
-
|
|
2550
|
+
callbacks.forEach(cb => {
|
|
2356
2551
|
// @ts-expect-error overload doesn't narrow within body
|
|
2357
2552
|
cb(identifier, value, key);
|
|
2358
2553
|
});
|
|
@@ -2360,7 +2555,6 @@ class NotificationManager {
|
|
|
2360
2555
|
}
|
|
2361
2556
|
destroy() {
|
|
2362
2557
|
this.isDestroyed = true;
|
|
2363
|
-
this._tokens.clear();
|
|
2364
2558
|
this._cache.clear();
|
|
2365
2559
|
}
|
|
2366
2560
|
}
|
|
@@ -2682,7 +2876,7 @@ class IdentifierArray {
|
|
|
2682
2876
|
return false;
|
|
2683
2877
|
}
|
|
2684
2878
|
const original = target[index];
|
|
2685
|
-
const newIdentifier = extractIdentifierFromRecord$
|
|
2879
|
+
const newIdentifier = extractIdentifierFromRecord$2(value);
|
|
2686
2880
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2687
2881
|
if (!test) {
|
|
2688
2882
|
throw new Error(`Expected a record`);
|
|
@@ -2723,7 +2917,7 @@ class IdentifierArray {
|
|
|
2723
2917
|
return Reflect.deleteProperty(target, prop);
|
|
2724
2918
|
},
|
|
2725
2919
|
getPrototypeOf() {
|
|
2726
|
-
return
|
|
2920
|
+
return Array.prototype;
|
|
2727
2921
|
}
|
|
2728
2922
|
});
|
|
2729
2923
|
createArrayTags(proxy, _SIGNAL);
|
|
@@ -2866,7 +3060,7 @@ Collection.prototype.query = null;
|
|
|
2866
3060
|
// Ensure instanceof works correctly
|
|
2867
3061
|
// Object.setPrototypeOf(IdentifierArray.prototype, Array.prototype);
|
|
2868
3062
|
|
|
2869
|
-
function assertRecordPassedToHasMany(record) {
|
|
3063
|
+
function assertRecordPassedToHasMany$1(record) {
|
|
2870
3064
|
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
2871
3065
|
if (!test) {
|
|
2872
3066
|
throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed $${typeof record}`);
|
|
@@ -2880,11 +3074,11 @@ function assertRecordPassedToHasMany(record) {
|
|
|
2880
3074
|
}
|
|
2881
3075
|
}()) : {};
|
|
2882
3076
|
}
|
|
2883
|
-
function extractIdentifierFromRecord$
|
|
3077
|
+
function extractIdentifierFromRecord$2(record) {
|
|
2884
3078
|
if (!record) {
|
|
2885
3079
|
return null;
|
|
2886
3080
|
}
|
|
2887
|
-
assertRecordPassedToHasMany(record);
|
|
3081
|
+
assertRecordPassedToHasMany$1(record);
|
|
2888
3082
|
return recordIdentifierFor(record);
|
|
2889
3083
|
}
|
|
2890
3084
|
|
|
@@ -2979,6 +3173,9 @@ class RecordArrayManager {
|
|
|
2979
3173
|
sync(array, pending, this._set.get(array));
|
|
2980
3174
|
this._pending.delete(array);
|
|
2981
3175
|
}
|
|
3176
|
+
mutate(mutation) {
|
|
3177
|
+
this.store.cache.mutate(mutation);
|
|
3178
|
+
}
|
|
2982
3179
|
|
|
2983
3180
|
/**
|
|
2984
3181
|
Get the `RecordArray` for a modelName, which contains all loaded records of
|
|
@@ -3495,6 +3692,118 @@ function constructResource(type, id, lid) {
|
|
|
3495
3692
|
*/
|
|
3496
3693
|
// this import location is deprecated but breaks in 4.8 and older
|
|
3497
3694
|
|
|
3695
|
+
// @ts-expect-error adding to globalThis
|
|
3696
|
+
globalThis.setWarpDriveLogging = setLogging;
|
|
3697
|
+
|
|
3698
|
+
// @ts-expect-error adding to globalThis
|
|
3699
|
+
globalThis.getWarpDriveRuntimeConfig = getRuntimeConfig;
|
|
3700
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
|
|
3701
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
|
|
3702
|
+
// @ts-expect-error adding to globalThis
|
|
3703
|
+
// eslint-disable-next-line
|
|
3704
|
+
globalThis.__WarpDriveMetricCountData = globalThis.__WarpDriveMetricCountData || {};
|
|
3705
|
+
|
|
3706
|
+
// @ts-expect-error adding to globalThis
|
|
3707
|
+
globalThis.getWarpDriveMetricCounts = () => {
|
|
3708
|
+
// @ts-expect-error
|
|
3709
|
+
// eslint-disable-next-line
|
|
3710
|
+
return structuredClone(globalThis.__WarpDriveMetricCountData);
|
|
3711
|
+
};
|
|
3712
|
+
|
|
3713
|
+
// @ts-expect-error adding to globalThis
|
|
3714
|
+
globalThis.resetWarpDriveMetricCounts = () => {
|
|
3715
|
+
// @ts-expect-error
|
|
3716
|
+
globalThis.__WarpDriveMetricCountData = {};
|
|
3717
|
+
};
|
|
3718
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS)) {
|
|
3719
|
+
if (getGlobalConfig().WarpDrive.debug.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS) {
|
|
3720
|
+
// @ts-expect-error adding to globalThis
|
|
3721
|
+
globalThis.__primitiveInstanceId = 0;
|
|
3722
|
+
function interceptAndLog(klassName, methodName) {
|
|
3723
|
+
const klass = globalThis[klassName];
|
|
3724
|
+
if (methodName === 'constructor') {
|
|
3725
|
+
const instantiationLabel = `new ${klassName}()`;
|
|
3726
|
+
// @ts-expect-error
|
|
3727
|
+
globalThis[klassName] = class extends klass {
|
|
3728
|
+
// @ts-expect-error
|
|
3729
|
+
constructor(...args) {
|
|
3730
|
+
// eslint-disable-next-line
|
|
3731
|
+
super(...args);
|
|
3732
|
+
// @ts-expect-error
|
|
3733
|
+
|
|
3734
|
+
const instanceId = globalThis.__primitiveInstanceId++;
|
|
3735
|
+
// @ts-expect-error
|
|
3736
|
+
// eslint-disable-next-line
|
|
3737
|
+
globalThis.__WarpDriveMetricCountData[instantiationLabel] =
|
|
3738
|
+
// @ts-expect-error
|
|
3739
|
+
// eslint-disable-next-line
|
|
3740
|
+
(globalThis.__WarpDriveMetricCountData[instantiationLabel] || 0) + 1;
|
|
3741
|
+
// @ts-expect-error
|
|
3742
|
+
this.instanceName = `${klassName}:${instanceId} - ${new Error().stack?.split('\n')[2]}`;
|
|
3743
|
+
}
|
|
3744
|
+
};
|
|
3745
|
+
} else {
|
|
3746
|
+
// @ts-expect-error
|
|
3747
|
+
// eslint-disable-next-line
|
|
3748
|
+
const original = klass.prototype[methodName];
|
|
3749
|
+
const logName = `${klassName}.${methodName}`;
|
|
3750
|
+
|
|
3751
|
+
// @ts-expect-error
|
|
3752
|
+
klass.prototype[methodName] = function (...args) {
|
|
3753
|
+
// @ts-expect-error
|
|
3754
|
+
// eslint-disable-next-line
|
|
3755
|
+
globalThis.__WarpDriveMetricCountData[logName] = (globalThis.__WarpDriveMetricCountData[logName] || 0) + 1;
|
|
3756
|
+
// @ts-expect-error
|
|
3757
|
+
const {
|
|
3758
|
+
instanceName
|
|
3759
|
+
} = this;
|
|
3760
|
+
if (!instanceName) {
|
|
3761
|
+
// @ts-expect-error
|
|
3762
|
+
const instanceId = globalThis.__primitiveInstanceId++;
|
|
3763
|
+
// @ts-expect-error
|
|
3764
|
+
this.instanceName = `${klassName}.${methodName}:${instanceId} - ${new Error().stack?.split('\n')[2]}`;
|
|
3765
|
+
}
|
|
3766
|
+
const instanceLogName = `${logName} (${instanceName})`;
|
|
3767
|
+
// @ts-expect-error
|
|
3768
|
+
// eslint-disable-next-line
|
|
3769
|
+
globalThis.__WarpDriveMetricCountData[instanceLogName] =
|
|
3770
|
+
// @ts-expect-error
|
|
3771
|
+
// eslint-disable-next-line
|
|
3772
|
+
(globalThis.__WarpDriveMetricCountData[instanceLogName] || 0) + 1;
|
|
3773
|
+
// eslint-disable-next-line
|
|
3774
|
+
return original.apply(this, args);
|
|
3775
|
+
};
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
interceptAndLog('Set', 'constructor');
|
|
3779
|
+
interceptAndLog('Set', 'add');
|
|
3780
|
+
interceptAndLog('Set', 'delete');
|
|
3781
|
+
interceptAndLog('Set', 'has');
|
|
3782
|
+
interceptAndLog('Set', 'set');
|
|
3783
|
+
interceptAndLog('Set', 'get');
|
|
3784
|
+
interceptAndLog('Map', 'constructor');
|
|
3785
|
+
interceptAndLog('Map', 'set');
|
|
3786
|
+
interceptAndLog('Map', 'delete');
|
|
3787
|
+
interceptAndLog('Map', 'has');
|
|
3788
|
+
interceptAndLog('Map', 'add');
|
|
3789
|
+
interceptAndLog('Map', 'get');
|
|
3790
|
+
interceptAndLog('WeakSet', 'constructor');
|
|
3791
|
+
interceptAndLog('WeakSet', 'add');
|
|
3792
|
+
interceptAndLog('WeakSet', 'delete');
|
|
3793
|
+
interceptAndLog('WeakSet', 'has');
|
|
3794
|
+
interceptAndLog('WeakSet', 'set');
|
|
3795
|
+
interceptAndLog('WeakSet', 'get');
|
|
3796
|
+
interceptAndLog('WeakMap', 'constructor');
|
|
3797
|
+
interceptAndLog('WeakMap', 'set');
|
|
3798
|
+
interceptAndLog('WeakMap', 'delete');
|
|
3799
|
+
interceptAndLog('WeakMap', 'has');
|
|
3800
|
+
interceptAndLog('WeakMap', 'add');
|
|
3801
|
+
interceptAndLog('WeakMap', 'get');
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
|
|
3498
3807
|
// `AwaitedKeys` is needed here to resolve any promise types like `PromiseBelongsTo`.
|
|
3499
3808
|
|
|
3500
3809
|
/**
|
|
@@ -3622,12 +3931,9 @@ class Store extends BaseClass {
|
|
|
3622
3931
|
* import Fetch from '@ember-data/request/fetch';
|
|
3623
3932
|
*
|
|
3624
3933
|
* class extends Store {
|
|
3625
|
-
*
|
|
3626
|
-
*
|
|
3627
|
-
*
|
|
3628
|
-
* this.requestManager.use([Fetch]);
|
|
3629
|
-
* this.requestManager.useCache(CacheHandler);
|
|
3630
|
-
* }
|
|
3934
|
+
* requestManager = new RequestManager()
|
|
3935
|
+
* .use([Fetch])
|
|
3936
|
+
* .useCache(CacheHandler);
|
|
3631
3937
|
* }
|
|
3632
3938
|
* ```
|
|
3633
3939
|
*
|
|
@@ -3869,7 +4175,7 @@ class Store extends BaseClass {
|
|
|
3869
4175
|
// the user has had the chance to set the prop.
|
|
3870
4176
|
const opts = {
|
|
3871
4177
|
store: this,
|
|
3872
|
-
[EnableHydration]: true
|
|
4178
|
+
[EnableHydration]: requestConfig[EnableHydration] ?? true
|
|
3873
4179
|
};
|
|
3874
4180
|
if (requestConfig.records) {
|
|
3875
4181
|
const identifierCache = this.identifierCache;
|
|
@@ -3880,22 +4186,26 @@ class Store extends BaseClass {
|
|
|
3880
4186
|
opts.disableTestWaiter = typeof requestConfig.disableTestWaiter === 'boolean' ? requestConfig.disableTestWaiter : true;
|
|
3881
4187
|
}
|
|
3882
4188
|
}
|
|
3883
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
4189
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_REQUESTS)) {
|
|
4190
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_REQUESTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_REQUESTS) {
|
|
4191
|
+
let options;
|
|
4192
|
+
try {
|
|
4193
|
+
options = JSON.parse(JSON.stringify(requestConfig));
|
|
4194
|
+
} catch {
|
|
4195
|
+
options = requestConfig;
|
|
4196
|
+
}
|
|
4197
|
+
// eslint-disable-next-line no-console
|
|
4198
|
+
console.log(`request: [[START]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`, options);
|
|
3889
4199
|
}
|
|
3890
|
-
// eslint-disable-next-line no-console
|
|
3891
|
-
console.log(`request: [[START]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`, options);
|
|
3892
4200
|
}
|
|
3893
4201
|
const request = Object.assign({}, requestConfig, opts);
|
|
3894
4202
|
const future = this.requestManager.request(request);
|
|
3895
4203
|
future.onFinalize(() => {
|
|
3896
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
3897
|
-
|
|
3898
|
-
|
|
4204
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_REQUESTS)) {
|
|
4205
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_REQUESTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_REQUESTS) {
|
|
4206
|
+
// eslint-disable-next-line no-console
|
|
4207
|
+
console.log(`request: [[FINALIZE]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`);
|
|
4208
|
+
}
|
|
3899
4209
|
}
|
|
3900
4210
|
// skip flush for legacy belongsTo
|
|
3901
4211
|
if (requestConfig.op === 'findBelongsTo' && !requestConfig.url) {
|
|
@@ -4101,9 +4411,8 @@ class Store extends BaseClass {
|
|
|
4101
4411
|
This will cause the record to be destroyed and freed up for garbage collection.
|
|
4102
4412
|
Example
|
|
4103
4413
|
```javascript
|
|
4104
|
-
store.findRecord('post', '1')
|
|
4105
|
-
|
|
4106
|
-
});
|
|
4414
|
+
const { content: { data: post } } = await store.request(findRecord({ type: 'post', id: '1' }));
|
|
4415
|
+
store.unloadRecord(post);
|
|
4107
4416
|
```
|
|
4108
4417
|
@method unloadRecord
|
|
4109
4418
|
@public
|
|
@@ -5155,14 +5464,16 @@ class Store extends BaseClass {
|
|
|
5155
5464
|
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5156
5465
|
assertDestroyingStore(this, '_push');
|
|
5157
5466
|
}
|
|
5158
|
-
if (macroCondition(getGlobalConfig().WarpDrive.
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5467
|
+
if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_PAYLOADS)) {
|
|
5468
|
+
if (getGlobalConfig().WarpDrive.debug.LOG_PAYLOADS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_PAYLOADS) {
|
|
5469
|
+
try {
|
|
5470
|
+
const data = JSON.parse(JSON.stringify(jsonApiDoc));
|
|
5471
|
+
// eslint-disable-next-line no-console
|
|
5472
|
+
console.log('EmberData | Payload - push', data);
|
|
5473
|
+
} catch {
|
|
5474
|
+
// eslint-disable-next-line no-console
|
|
5475
|
+
console.log('EmberData | Payload - push', jsonApiDoc);
|
|
5476
|
+
}
|
|
5166
5477
|
}
|
|
5167
5478
|
}
|
|
5168
5479
|
if (asyncFlush) {
|
|
@@ -5385,9 +5696,9 @@ function normalizeProperties(store, identifier, properties) {
|
|
|
5385
5696
|
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
5386
5697
|
assertRecordsPassedToHasMany(properties[prop]);
|
|
5387
5698
|
}
|
|
5388
|
-
properties[prop] = extractIdentifiersFromRecords(properties[prop]);
|
|
5699
|
+
properties[prop] = extractIdentifiersFromRecords$1(properties[prop]);
|
|
5389
5700
|
} else if (field.kind === 'belongsTo') {
|
|
5390
|
-
properties[prop] = extractIdentifierFromRecord(properties[prop]);
|
|
5701
|
+
properties[prop] = extractIdentifierFromRecord$1(properties[prop]);
|
|
5391
5702
|
}
|
|
5392
5703
|
}
|
|
5393
5704
|
}
|
|
@@ -5415,10 +5726,10 @@ function assertRecordsPassedToHasMany(records) {
|
|
|
5415
5726
|
});
|
|
5416
5727
|
}()) : {};
|
|
5417
5728
|
}
|
|
5418
|
-
function extractIdentifiersFromRecords(records) {
|
|
5419
|
-
return records.map(record => extractIdentifierFromRecord(record));
|
|
5729
|
+
function extractIdentifiersFromRecords$1(records) {
|
|
5730
|
+
return records.map(record => extractIdentifierFromRecord$1(record));
|
|
5420
5731
|
}
|
|
5421
|
-
function extractIdentifierFromRecord(recordOrPromiseRecord) {
|
|
5732
|
+
function extractIdentifierFromRecord$1(recordOrPromiseRecord) {
|
|
5422
5733
|
if (!recordOrPromiseRecord) {
|
|
5423
5734
|
return null;
|
|
5424
5735
|
}
|
|
@@ -6066,4 +6377,475 @@ function fetchContentAndHydrate(next, context, identifier, priority) {
|
|
|
6066
6377
|
}]
|
|
6067
6378
|
});
|
|
6068
6379
|
}
|
|
6069
|
-
|
|
6380
|
+
|
|
6381
|
+
/**
|
|
6382
|
+
@module @ember-data/store
|
|
6383
|
+
*/
|
|
6384
|
+
/**
|
|
6385
|
+
A `ManyArray` is a `MutableArray` that represents the contents of a has-many
|
|
6386
|
+
relationship.
|
|
6387
|
+
|
|
6388
|
+
The `ManyArray` is instantiated lazily the first time the relationship is
|
|
6389
|
+
requested.
|
|
6390
|
+
|
|
6391
|
+
This class is not intended to be directly instantiated by consuming applications.
|
|
6392
|
+
|
|
6393
|
+
### Inverses
|
|
6394
|
+
|
|
6395
|
+
Often, the relationships in Ember Data applications will have
|
|
6396
|
+
an inverse. For example, imagine the following models are
|
|
6397
|
+
defined:
|
|
6398
|
+
|
|
6399
|
+
```app/models/post.js
|
|
6400
|
+
import Model, { hasMany } from '@ember-data/model';
|
|
6401
|
+
|
|
6402
|
+
export default class PostModel extends Model {
|
|
6403
|
+
@hasMany('comment') comments;
|
|
6404
|
+
}
|
|
6405
|
+
```
|
|
6406
|
+
|
|
6407
|
+
```app/models/comment.js
|
|
6408
|
+
import Model, { belongsTo } from '@ember-data/model';
|
|
6409
|
+
|
|
6410
|
+
export default class CommentModel extends Model {
|
|
6411
|
+
@belongsTo('post') post;
|
|
6412
|
+
}
|
|
6413
|
+
```
|
|
6414
|
+
|
|
6415
|
+
If you created a new instance of `Post` and added
|
|
6416
|
+
a `Comment` record to its `comments` has-many
|
|
6417
|
+
relationship, you would expect the comment's `post`
|
|
6418
|
+
property to be set to the post that contained
|
|
6419
|
+
the has-many.
|
|
6420
|
+
|
|
6421
|
+
We call the record to which a relationship belongs-to the
|
|
6422
|
+
relationship's _owner_.
|
|
6423
|
+
|
|
6424
|
+
@class ManyArray
|
|
6425
|
+
@public
|
|
6426
|
+
*/
|
|
6427
|
+
class RelatedCollection extends IdentifierArray {
|
|
6428
|
+
/**
|
|
6429
|
+
The loading state of this array
|
|
6430
|
+
@property {Boolean} isLoaded
|
|
6431
|
+
@public
|
|
6432
|
+
*/
|
|
6433
|
+
|
|
6434
|
+
/**
|
|
6435
|
+
`true` if the relationship is polymorphic, `false` otherwise.
|
|
6436
|
+
@property {Boolean} isPolymorphic
|
|
6437
|
+
@private
|
|
6438
|
+
*/
|
|
6439
|
+
|
|
6440
|
+
/**
|
|
6441
|
+
Metadata associated with the request for async hasMany relationships.
|
|
6442
|
+
Example
|
|
6443
|
+
Given that the server returns the following JSON payload when fetching a
|
|
6444
|
+
hasMany relationship:
|
|
6445
|
+
```js
|
|
6446
|
+
{
|
|
6447
|
+
"comments": [{
|
|
6448
|
+
"id": 1,
|
|
6449
|
+
"comment": "This is the first comment",
|
|
6450
|
+
}, {
|
|
6451
|
+
// ...
|
|
6452
|
+
}],
|
|
6453
|
+
"meta": {
|
|
6454
|
+
"page": 1,
|
|
6455
|
+
"total": 5
|
|
6456
|
+
}
|
|
6457
|
+
}
|
|
6458
|
+
```
|
|
6459
|
+
You can then access the meta data via the `meta` property:
|
|
6460
|
+
```js
|
|
6461
|
+
let comments = await post.comments;
|
|
6462
|
+
let meta = comments.meta;
|
|
6463
|
+
// meta.page => 1
|
|
6464
|
+
// meta.total => 5
|
|
6465
|
+
```
|
|
6466
|
+
@property {Object | null} meta
|
|
6467
|
+
@public
|
|
6468
|
+
*/
|
|
6469
|
+
|
|
6470
|
+
/**
|
|
6471
|
+
* Retrieve the links for this relationship
|
|
6472
|
+
*
|
|
6473
|
+
@property {Object | null} links
|
|
6474
|
+
@public
|
|
6475
|
+
*/
|
|
6476
|
+
|
|
6477
|
+
constructor(options) {
|
|
6478
|
+
super(options);
|
|
6479
|
+
this.isLoaded = options.isLoaded || false;
|
|
6480
|
+
this.isAsync = options.isAsync || false;
|
|
6481
|
+
this.isPolymorphic = options.isPolymorphic || false;
|
|
6482
|
+
this.identifier = options.identifier;
|
|
6483
|
+
this.key = options.key;
|
|
6484
|
+
}
|
|
6485
|
+
[MUTATE](target, receiver, prop, args, _SIGNAL) {
|
|
6486
|
+
switch (prop) {
|
|
6487
|
+
case 'length 0':
|
|
6488
|
+
{
|
|
6489
|
+
Reflect.set(target, 'length', 0);
|
|
6490
|
+
mutateReplaceRelatedRecords(this, [], _SIGNAL);
|
|
6491
|
+
return true;
|
|
6492
|
+
}
|
|
6493
|
+
case 'replace cell':
|
|
6494
|
+
{
|
|
6495
|
+
const [index, prior, value] = args;
|
|
6496
|
+
target[index] = value;
|
|
6497
|
+
mutateReplaceRelatedRecord(this, {
|
|
6498
|
+
value,
|
|
6499
|
+
prior,
|
|
6500
|
+
index
|
|
6501
|
+
}, _SIGNAL);
|
|
6502
|
+
return true;
|
|
6503
|
+
}
|
|
6504
|
+
case 'push':
|
|
6505
|
+
{
|
|
6506
|
+
const newValues = extractIdentifiersFromRecords(args);
|
|
6507
|
+
assertNoDuplicates(this, target, currentState => currentState.push(...newValues), `Cannot push duplicates to a hasMany's state.`);
|
|
6508
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6509
|
+
// dedupe
|
|
6510
|
+
const seen = new Set(target);
|
|
6511
|
+
const unique = new Set();
|
|
6512
|
+
args.forEach(item => {
|
|
6513
|
+
const identifier = recordIdentifierFor(item);
|
|
6514
|
+
if (!seen.has(identifier)) {
|
|
6515
|
+
seen.add(identifier);
|
|
6516
|
+
unique.add(item);
|
|
6517
|
+
}
|
|
6518
|
+
});
|
|
6519
|
+
const newArgs = Array.from(unique);
|
|
6520
|
+
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
6521
|
+
if (newArgs.length) {
|
|
6522
|
+
mutateAddToRelatedRecords(this, {
|
|
6523
|
+
value: extractIdentifiersFromRecords(newArgs)
|
|
6524
|
+
}, _SIGNAL);
|
|
6525
|
+
}
|
|
6526
|
+
return result;
|
|
6527
|
+
}
|
|
6528
|
+
|
|
6529
|
+
// else, no dedupe, error on duplicates
|
|
6530
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6531
|
+
if (newValues.length) {
|
|
6532
|
+
mutateAddToRelatedRecords(this, {
|
|
6533
|
+
value: newValues
|
|
6534
|
+
}, _SIGNAL);
|
|
6535
|
+
}
|
|
6536
|
+
return result;
|
|
6537
|
+
}
|
|
6538
|
+
case 'pop':
|
|
6539
|
+
{
|
|
6540
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6541
|
+
if (result) {
|
|
6542
|
+
mutateRemoveFromRelatedRecords(this, {
|
|
6543
|
+
value: recordIdentifierFor(result)
|
|
6544
|
+
}, _SIGNAL);
|
|
6545
|
+
}
|
|
6546
|
+
return result;
|
|
6547
|
+
}
|
|
6548
|
+
case 'unshift':
|
|
6549
|
+
{
|
|
6550
|
+
const newValues = extractIdentifiersFromRecords(args);
|
|
6551
|
+
assertNoDuplicates(this, target, currentState => currentState.unshift(...newValues), `Cannot unshift duplicates to a hasMany's state.`);
|
|
6552
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6553
|
+
// dedupe
|
|
6554
|
+
const seen = new Set(target);
|
|
6555
|
+
const unique = new Set();
|
|
6556
|
+
args.forEach(item => {
|
|
6557
|
+
const identifier = recordIdentifierFor(item);
|
|
6558
|
+
if (!seen.has(identifier)) {
|
|
6559
|
+
seen.add(identifier);
|
|
6560
|
+
unique.add(item);
|
|
6561
|
+
}
|
|
6562
|
+
});
|
|
6563
|
+
const newArgs = Array.from(unique);
|
|
6564
|
+
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
6565
|
+
if (newArgs.length) {
|
|
6566
|
+
mutateAddToRelatedRecords(this, {
|
|
6567
|
+
value: extractIdentifiersFromRecords(newArgs),
|
|
6568
|
+
index: 0
|
|
6569
|
+
}, _SIGNAL);
|
|
6570
|
+
}
|
|
6571
|
+
return result;
|
|
6572
|
+
}
|
|
6573
|
+
|
|
6574
|
+
// else, no dedupe, error on duplicates
|
|
6575
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6576
|
+
if (newValues.length) {
|
|
6577
|
+
mutateAddToRelatedRecords(this, {
|
|
6578
|
+
value: newValues,
|
|
6579
|
+
index: 0
|
|
6580
|
+
}, _SIGNAL);
|
|
6581
|
+
}
|
|
6582
|
+
return result;
|
|
6583
|
+
}
|
|
6584
|
+
case 'shift':
|
|
6585
|
+
{
|
|
6586
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6587
|
+
if (result) {
|
|
6588
|
+
mutateRemoveFromRelatedRecords(this, {
|
|
6589
|
+
value: recordIdentifierFor(result),
|
|
6590
|
+
index: 0
|
|
6591
|
+
}, _SIGNAL);
|
|
6592
|
+
}
|
|
6593
|
+
return result;
|
|
6594
|
+
}
|
|
6595
|
+
case 'sort':
|
|
6596
|
+
{
|
|
6597
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6598
|
+
mutateSortRelatedRecords(this, result.map(recordIdentifierFor), _SIGNAL);
|
|
6599
|
+
return result;
|
|
6600
|
+
}
|
|
6601
|
+
case 'splice':
|
|
6602
|
+
{
|
|
6603
|
+
const [start, deleteCount, ...adds] = args;
|
|
6604
|
+
|
|
6605
|
+
// detect a full replace
|
|
6606
|
+
if (start === 0 && deleteCount === this[SOURCE].length) {
|
|
6607
|
+
const newValues = extractIdentifiersFromRecords(adds);
|
|
6608
|
+
assertNoDuplicates(this, target, currentState => currentState.splice(start, deleteCount, ...newValues), `Cannot replace a hasMany's state with a new state that contains duplicates.`);
|
|
6609
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6610
|
+
// dedupe
|
|
6611
|
+
const current = new Set(adds);
|
|
6612
|
+
const unique = Array.from(current);
|
|
6613
|
+
const newArgs = [start, deleteCount].concat(unique);
|
|
6614
|
+
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
6615
|
+
mutateReplaceRelatedRecords(this, extractIdentifiersFromRecords(unique), _SIGNAL);
|
|
6616
|
+
return result;
|
|
6617
|
+
}
|
|
6618
|
+
|
|
6619
|
+
// else, no dedupe, error on duplicates
|
|
6620
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6621
|
+
mutateReplaceRelatedRecords(this, newValues, _SIGNAL);
|
|
6622
|
+
return result;
|
|
6623
|
+
}
|
|
6624
|
+
const newValues = extractIdentifiersFromRecords(adds);
|
|
6625
|
+
assertNoDuplicates(this, target, currentState => currentState.splice(start, deleteCount, ...newValues), `Cannot splice a hasMany's state with a new state that contains duplicates.`);
|
|
6626
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6627
|
+
// dedupe
|
|
6628
|
+
const currentState = target.slice();
|
|
6629
|
+
currentState.splice(start, deleteCount);
|
|
6630
|
+
const seen = new Set(currentState);
|
|
6631
|
+
const unique = [];
|
|
6632
|
+
adds.forEach(item => {
|
|
6633
|
+
const identifier = recordIdentifierFor(item);
|
|
6634
|
+
if (!seen.has(identifier)) {
|
|
6635
|
+
seen.add(identifier);
|
|
6636
|
+
unique.push(item);
|
|
6637
|
+
}
|
|
6638
|
+
});
|
|
6639
|
+
const newArgs = [start, deleteCount, ...unique];
|
|
6640
|
+
const result = Reflect.apply(target[prop], receiver, newArgs);
|
|
6641
|
+
if (deleteCount > 0) {
|
|
6642
|
+
mutateRemoveFromRelatedRecords(this, {
|
|
6643
|
+
value: result.map(recordIdentifierFor),
|
|
6644
|
+
index: start
|
|
6645
|
+
}, _SIGNAL);
|
|
6646
|
+
}
|
|
6647
|
+
if (unique.length > 0) {
|
|
6648
|
+
mutateAddToRelatedRecords(this, {
|
|
6649
|
+
value: extractIdentifiersFromRecords(unique),
|
|
6650
|
+
index: start
|
|
6651
|
+
}, _SIGNAL);
|
|
6652
|
+
}
|
|
6653
|
+
return result;
|
|
6654
|
+
}
|
|
6655
|
+
|
|
6656
|
+
// else, no dedupe, error on duplicates
|
|
6657
|
+
const result = Reflect.apply(target[prop], receiver, args);
|
|
6658
|
+
if (deleteCount > 0) {
|
|
6659
|
+
mutateRemoveFromRelatedRecords(this, {
|
|
6660
|
+
value: result.map(recordIdentifierFor),
|
|
6661
|
+
index: start
|
|
6662
|
+
}, _SIGNAL);
|
|
6663
|
+
}
|
|
6664
|
+
if (newValues.length > 0) {
|
|
6665
|
+
mutateAddToRelatedRecords(this, {
|
|
6666
|
+
value: newValues,
|
|
6667
|
+
index: start
|
|
6668
|
+
}, _SIGNAL);
|
|
6669
|
+
}
|
|
6670
|
+
return result;
|
|
6671
|
+
}
|
|
6672
|
+
default:
|
|
6673
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6674
|
+
{
|
|
6675
|
+
throw new Error(`unable to convert ${prop} into a transaction that updates the cache state for this record array`);
|
|
6676
|
+
}
|
|
6677
|
+
})() : {};
|
|
6678
|
+
}
|
|
6679
|
+
}
|
|
6680
|
+
notify() {
|
|
6681
|
+
const signal = this[ARRAY_SIGNAL];
|
|
6682
|
+
signal.shouldReset = true;
|
|
6683
|
+
notifyArray(this);
|
|
6684
|
+
}
|
|
6685
|
+
|
|
6686
|
+
/**
|
|
6687
|
+
Reloads all of the records in the manyArray. If the manyArray
|
|
6688
|
+
holds a relationship that was originally fetched using a links url
|
|
6689
|
+
EmberData will revisit the original links url to repopulate the
|
|
6690
|
+
relationship.
|
|
6691
|
+
If the ManyArray holds the result of a `store.query()` reload will
|
|
6692
|
+
re-run the original query.
|
|
6693
|
+
Example
|
|
6694
|
+
```javascript
|
|
6695
|
+
let user = store.peekRecord('user', '1')
|
|
6696
|
+
await login(user);
|
|
6697
|
+
let permissions = await user.permissions;
|
|
6698
|
+
await permissions.reload();
|
|
6699
|
+
```
|
|
6700
|
+
@method reload
|
|
6701
|
+
@public
|
|
6702
|
+
*/
|
|
6703
|
+
reload(options) {
|
|
6704
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6705
|
+
if (!test) {
|
|
6706
|
+
throw new Error(`Expected the manager for ManyArray to implement reloadHasMany`);
|
|
6707
|
+
}
|
|
6708
|
+
})(typeof this._manager.reloadHasMany === 'function') : {};
|
|
6709
|
+
// TODO this is odd, we don't ask the store for anything else like this?
|
|
6710
|
+
return this._manager.reloadHasMany(this.key, options);
|
|
6711
|
+
}
|
|
6712
|
+
|
|
6713
|
+
/**
|
|
6714
|
+
Saves all of the records in the `ManyArray`.
|
|
6715
|
+
Note: this API can only be used in legacy mode with a configured Adapter.
|
|
6716
|
+
Example
|
|
6717
|
+
```javascript
|
|
6718
|
+
const { content: { data: inbox } } = await store.request(findRecord({ type: 'inbox', id: '1' }));
|
|
6719
|
+
let messages = await inbox.messages;
|
|
6720
|
+
messages.forEach((message) => {
|
|
6721
|
+
message.isRead = true;
|
|
6722
|
+
});
|
|
6723
|
+
messages.save();
|
|
6724
|
+
```
|
|
6725
|
+
@method save
|
|
6726
|
+
@public
|
|
6727
|
+
@return {PromiseArray} promise
|
|
6728
|
+
*/
|
|
6729
|
+
|
|
6730
|
+
/**
|
|
6731
|
+
Create a child record within the owner
|
|
6732
|
+
@method createRecord
|
|
6733
|
+
@public
|
|
6734
|
+
@param {Object} hash
|
|
6735
|
+
@return {Model} record
|
|
6736
|
+
*/
|
|
6737
|
+
createRecord(hash) {
|
|
6738
|
+
const {
|
|
6739
|
+
store
|
|
6740
|
+
} = this;
|
|
6741
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6742
|
+
if (!test) {
|
|
6743
|
+
throw new Error(`Expected modelName to be set`);
|
|
6744
|
+
}
|
|
6745
|
+
})(this.modelName) : {};
|
|
6746
|
+
const record = store.createRecord(this.modelName, hash);
|
|
6747
|
+
this.push(record);
|
|
6748
|
+
return record;
|
|
6749
|
+
}
|
|
6750
|
+
destroy() {
|
|
6751
|
+
super.destroy(false);
|
|
6752
|
+
}
|
|
6753
|
+
}
|
|
6754
|
+
RelatedCollection.prototype.isAsync = false;
|
|
6755
|
+
RelatedCollection.prototype.isPolymorphic = false;
|
|
6756
|
+
RelatedCollection.prototype.identifier = null;
|
|
6757
|
+
RelatedCollection.prototype.cache = null;
|
|
6758
|
+
RelatedCollection.prototype._inverseIsAsync = false;
|
|
6759
|
+
RelatedCollection.prototype.key = '';
|
|
6760
|
+
RelatedCollection.prototype.DEPRECATED_CLASS_NAME = 'ManyArray';
|
|
6761
|
+
function assertRecordPassedToHasMany(record) {
|
|
6762
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6763
|
+
if (!test) {
|
|
6764
|
+
throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed ${typeof record}`);
|
|
6765
|
+
}
|
|
6766
|
+
})(function () {
|
|
6767
|
+
try {
|
|
6768
|
+
recordIdentifierFor(record);
|
|
6769
|
+
return true;
|
|
6770
|
+
} catch {
|
|
6771
|
+
return false;
|
|
6772
|
+
}
|
|
6773
|
+
}()) : {};
|
|
6774
|
+
}
|
|
6775
|
+
function extractIdentifiersFromRecords(records) {
|
|
6776
|
+
return records.map(extractIdentifierFromRecord);
|
|
6777
|
+
}
|
|
6778
|
+
function extractIdentifierFromRecord(recordOrPromiseRecord) {
|
|
6779
|
+
assertRecordPassedToHasMany(recordOrPromiseRecord);
|
|
6780
|
+
return recordIdentifierFor(recordOrPromiseRecord);
|
|
6781
|
+
}
|
|
6782
|
+
function assertNoDuplicates(collection, target, callback, reason) {
|
|
6783
|
+
const state = target.slice();
|
|
6784
|
+
callback(state);
|
|
6785
|
+
if (state.length !== new Set(state).size) {
|
|
6786
|
+
const duplicates = state.filter((currentValue, currentIndex) => state.indexOf(currentValue) !== currentIndex);
|
|
6787
|
+
if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
|
|
6788
|
+
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, {
|
|
6789
|
+
id: 'ember-data:deprecate-many-array-duplicates',
|
|
6790
|
+
for: 'ember-data',
|
|
6791
|
+
until: '6.0',
|
|
6792
|
+
since: {
|
|
6793
|
+
enabled: '5.3',
|
|
6794
|
+
available: '4.13'
|
|
6795
|
+
}
|
|
6796
|
+
});
|
|
6797
|
+
} else {
|
|
6798
|
+
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- ')}`);
|
|
6799
|
+
}
|
|
6800
|
+
}
|
|
6801
|
+
}
|
|
6802
|
+
function mutateAddToRelatedRecords(collection, operationInfo, _SIGNAL) {
|
|
6803
|
+
mutate(collection, {
|
|
6804
|
+
op: 'addToRelatedRecords',
|
|
6805
|
+
record: collection.identifier,
|
|
6806
|
+
field: collection.key,
|
|
6807
|
+
...operationInfo
|
|
6808
|
+
}, _SIGNAL);
|
|
6809
|
+
}
|
|
6810
|
+
function mutateRemoveFromRelatedRecords(collection, operationInfo, _SIGNAL) {
|
|
6811
|
+
mutate(collection, {
|
|
6812
|
+
op: 'removeFromRelatedRecords',
|
|
6813
|
+
record: collection.identifier,
|
|
6814
|
+
field: collection.key,
|
|
6815
|
+
...operationInfo
|
|
6816
|
+
}, _SIGNAL);
|
|
6817
|
+
}
|
|
6818
|
+
function mutateReplaceRelatedRecord(collection, operationInfo, _SIGNAL) {
|
|
6819
|
+
mutate(collection, {
|
|
6820
|
+
op: 'replaceRelatedRecord',
|
|
6821
|
+
record: collection.identifier,
|
|
6822
|
+
field: collection.key,
|
|
6823
|
+
...operationInfo
|
|
6824
|
+
}, _SIGNAL);
|
|
6825
|
+
}
|
|
6826
|
+
function mutateReplaceRelatedRecords(collection, value, _SIGNAL) {
|
|
6827
|
+
mutate(collection, {
|
|
6828
|
+
op: 'replaceRelatedRecords',
|
|
6829
|
+
record: collection.identifier,
|
|
6830
|
+
field: collection.key,
|
|
6831
|
+
value
|
|
6832
|
+
}, _SIGNAL);
|
|
6833
|
+
}
|
|
6834
|
+
function mutateSortRelatedRecords(collection, value, _SIGNAL) {
|
|
6835
|
+
mutate(collection, {
|
|
6836
|
+
op: 'sortRelatedRecords',
|
|
6837
|
+
record: collection.identifier,
|
|
6838
|
+
field: collection.key,
|
|
6839
|
+
value
|
|
6840
|
+
}, _SIGNAL);
|
|
6841
|
+
}
|
|
6842
|
+
function mutate(collection, mutation, _SIGNAL) {
|
|
6843
|
+
macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
|
|
6844
|
+
if (!test) {
|
|
6845
|
+
throw new Error(`Expected the manager for ManyArray to implement mutate`);
|
|
6846
|
+
}
|
|
6847
|
+
})(typeof collection._manager.mutate === 'function') : {};
|
|
6848
|
+
collection._manager.mutate(mutation);
|
|
6849
|
+
addToTransaction(_SIGNAL);
|
|
6850
|
+
}
|
|
6851
|
+
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, constructResource as f, coerceId as g, ensureStringId as h, isStableIdentifier as i, Collection as j, SOURCE as k, fastPush as l, removeRecordDataFor as m, notifyArray as n, setRecordIdentifier as o, peekCache as p, StoreMap as q, recordIdentifierFor as r, storeFor as s, setCacheFor as t, normalizeModelName as u, RelatedCollection as v, log as w, logGroup as x };
|