@ember-data/store 5.3.10 → 5.3.12

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.
Files changed (54) hide show
  1. package/LICENSE.md +19 -7
  2. package/README.md +5 -8
  3. package/dist/-private.js +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/{handler-CW2kp6Ua.js → many-array-uP6jS6_J.js} +966 -165
  6. package/dist/many-array-uP6jS6_J.js.map +1 -0
  7. package/logos/NCC-1701-a-blue.svg +4 -0
  8. package/logos/NCC-1701-a-gold.svg +4 -0
  9. package/logos/NCC-1701-a-gold_100.svg +1 -0
  10. package/logos/NCC-1701-a-gold_base-64.txt +1 -0
  11. package/logos/NCC-1701-a.svg +4 -0
  12. package/logos/README.md +4 -0
  13. package/logos/docs-badge.svg +2 -0
  14. package/logos/github-header.svg +444 -0
  15. package/logos/social1.png +0 -0
  16. package/logos/social2.png +0 -0
  17. package/logos/warp-drive-logo-dark.svg +4 -0
  18. package/logos/warp-drive-logo-gold.svg +4 -0
  19. package/package.json +24 -43
  20. package/unstable-preview-types/-private/cache-handler/handler.d.ts +0 -2
  21. package/unstable-preview-types/-private/cache-handler/handler.d.ts.map +1 -1
  22. package/unstable-preview-types/-private/caches/identifier-cache.d.ts.map +1 -1
  23. package/unstable-preview-types/-private/caches/instance-cache.d.ts.map +1 -1
  24. package/unstable-preview-types/-private/debug/utils.d.ts +9 -0
  25. package/unstable-preview-types/-private/debug/utils.d.ts.map +1 -0
  26. package/unstable-preview-types/-private/legacy-model-support/shim-model-class.d.ts +3 -3
  27. package/unstable-preview-types/-private/legacy-model-support/shim-model-class.d.ts.map +1 -1
  28. package/unstable-preview-types/-private/managers/cache-capabilities-manager.d.ts +3 -3
  29. package/unstable-preview-types/-private/managers/cache-capabilities-manager.d.ts.map +1 -1
  30. package/unstable-preview-types/-private/managers/cache-manager.d.ts +22 -0
  31. package/unstable-preview-types/-private/managers/cache-manager.d.ts.map +1 -1
  32. package/unstable-preview-types/-private/managers/notification-manager.d.ts +4 -4
  33. package/unstable-preview-types/-private/managers/notification-manager.d.ts.map +1 -1
  34. package/unstable-preview-types/-private/managers/record-array-manager.d.ts +2 -0
  35. package/unstable-preview-types/-private/managers/record-array-manager.d.ts.map +1 -1
  36. package/unstable-preview-types/-private/record-arrays/identifier-array.d.ts +11 -1
  37. package/unstable-preview-types/-private/record-arrays/identifier-array.d.ts.map +1 -1
  38. package/unstable-preview-types/-private/record-arrays/many-array.d.ts +199 -0
  39. package/unstable-preview-types/-private/record-arrays/many-array.d.ts.map +1 -0
  40. package/unstable-preview-types/-private/store-service.d.ts +64 -9
  41. package/unstable-preview-types/-private/store-service.d.ts.map +1 -1
  42. package/unstable-preview-types/-private.d.ts +2 -0
  43. package/unstable-preview-types/-private.d.ts.map +1 -1
  44. package/unstable-preview-types/-types/q/cache-capabilities-manager.d.ts +4 -4
  45. package/unstable-preview-types/-types/q/cache-capabilities-manager.d.ts.map +1 -1
  46. package/unstable-preview-types/-types/q/ds-model.d.ts +3 -3
  47. package/unstable-preview-types/-types/q/ds-model.d.ts.map +1 -1
  48. package/unstable-preview-types/-types/q/schema-service.d.ts +5 -5
  49. package/unstable-preview-types/-types/q/schema-service.d.ts.map +1 -1
  50. package/unstable-preview-types/index.d.ts +24 -25
  51. package/unstable-preview-types/index.d.ts.map +1 -1
  52. package/dist/handler-CW2kp6Ua.js.map +0 -1
  53. /package/{ember-data-logo-dark.svg → logos/ember-data-logo-dark.svg} +0 -0
  54. /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 { SkipCache, EnableHydration } from '@warp-drive/core-types/request';
4
- import { getOrSetGlobal, setTransient, peekTransient } from '@warp-drive/core-types/-private';
5
- import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_CLIENT_ORIGINATED, DEBUG_IDENTIFIER_BUCKET } from '@warp-drive/core-types/identifier';
6
- import { dasherize } from '@ember-data/request-utils/string';
7
- import { defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
3
+ import { EnableHydration, SkipCache } from '@warp-drive/core-types/request';
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 { 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 || IDENTIFIERS.has(identifier);
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.debug.LOG_IDENTIFIERS)) {
314
- // eslint-disable-next-line no-console
315
- console.groupCollapsed(`Identifiers: ${shouldGenerate ? 'Generating' : 'Peeking'} Identifier`, resource);
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.debug.LOG_IDENTIFIERS)) {
326
- // eslint-disable-next-line no-console
327
- console.log(`Identifiers: cache HIT - Stable ${resource.lid}`);
328
- // eslint-disable-next-line no-console
329
- console.groupEnd();
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.debug.LOG_IDENTIFIERS)) {
337
- // eslint-disable-next-line no-console
338
- console.log(`Identifiers: ${lid ? 'no ' : ''}lid ${lid ? lid + ' ' : ''}determined for resource`, resource);
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.debug.LOG_IDENTIFIERS)) {
343
- // eslint-disable-next-line no-console
344
- console.groupEnd();
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.debug.LOG_IDENTIFIERS)) {
350
- // eslint-disable-next-line no-console
351
- console.groupEnd();
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.debug.LOG_IDENTIFIERS)) {
370
- // eslint-disable-next-line no-console
371
- console.groupEnd();
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.debug.LOG_IDENTIFIERS)) {
466
- // eslint-disable-next-line no-console
467
- console.log(`Identifiers: created identifier ${String(identifier)} for newly generated resource`, data);
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.debug.LOG_IDENTIFIERS)) {
515
- // eslint-disable-next-line no-console
516
- console.log(`Identifiers: merged identifiers ${generatedIdentifier.lid} and ${existingIdentifier.lid} for resource into ${identifier.lid}`, data);
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.debug.LOG_IDENTIFIERS)) {
527
- // eslint-disable-next-line no-console
528
- console.log(`Identifiers: updated id for identifier ${identifier.lid} from '${String(id)}' to '${String(newId)}' for resource`, data);
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.debug.LOG_IDENTIFIERS)) {
541
- // eslint-disable-next-line no-console
542
- console.log(`Identifiers: updated identifier ${identifier.lid} resource`, data);
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.debug.LOG_IDENTIFIERS)) {
627
- // eslint-disable-next-line no-console
628
- console.log(`Identifiers: released identifier ${identifierObject.lid}`);
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
- get lid() {
646
- return recordIdentifier.lid;
647
- },
665
+ type: recordIdentifier.type,
666
+ lid: recordIdentifier.lid,
648
667
  get id() {
649
668
  return recordIdentifier.id;
650
- },
651
- get type() {
652
- return recordIdentifier.type;
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(wrapper, 'toString', {
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(wrapper, 'toJSON', {
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[DEBUG_CLIENT_ORIGINATED] = clientOriginated;
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.debug.LOG_IDENTIFIERS)) {
779
- // eslint-disable-next-line no-console
780
- console.log(`Identifiers: cache ${identifier ? 'HIT' : 'MISS'} - Non-Stable ${lid}`, resource);
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,6 +820,87 @@ 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
906
  @module @ember-data/store
@@ -1252,9 +1357,16 @@ class InstanceCache {
1252
1357
  setCacheFor(record, cache);
1253
1358
  StoreMap.set(record, this.store);
1254
1359
  this.__instances.record.set(identifier, record);
1255
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
1256
- // eslint-disable-next-line no-console
1257
- console.log(`InstanceCache: created Record for ${String(identifier)}`, properties);
1360
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
1361
+ if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
1362
+ logGroup('reactive-ui', '', identifier.type, identifier.lid, 'created', '');
1363
+ // eslint-disable-next-line no-console
1364
+ console.log({
1365
+ properties
1366
+ });
1367
+ // eslint-disable-next-line no-console
1368
+ console.groupEnd();
1369
+ }
1258
1370
  }
1259
1371
  }
1260
1372
  return record;
@@ -1300,9 +1412,10 @@ class InstanceCache {
1300
1412
  this.store.identifierCache.forgetRecordIdentifier(identifier);
1301
1413
  removeRecordDataFor(identifier);
1302
1414
  this.store._requestCache._clearEntries(identifier);
1303
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
1304
- // eslint-disable-next-line no-console
1305
- console.log(`InstanceCache: disconnected ${String(identifier)}`);
1415
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
1416
+ if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
1417
+ log('reactive-ui', '', identifier.type, identifier.lid, 'disconnected', '');
1418
+ }
1306
1419
  }
1307
1420
  }
1308
1421
  unloadRecord(identifier) {
@@ -1318,9 +1431,11 @@ class InstanceCache {
1318
1431
  })() : {};
1319
1432
  }
1320
1433
  }
1321
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
1322
- // eslint-disable-next-line no-console
1323
- console.groupCollapsed(`InstanceCache: unloading record for ${String(identifier)}`);
1434
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
1435
+ if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
1436
+ // eslint-disable-next-line no-console
1437
+ console.groupCollapsed(`InstanceCache: unloading record for ${String(identifier)}`);
1438
+ }
1324
1439
  }
1325
1440
 
1326
1441
  // TODO is this join still necessary?
@@ -1333,27 +1448,33 @@ class InstanceCache {
1333
1448
  StoreMap.delete(record);
1334
1449
  RecordCache.delete(record);
1335
1450
  removeRecordDataFor(record);
1336
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
1337
- // eslint-disable-next-line no-console
1338
- console.log(`InstanceCache: destroyed record for ${String(identifier)}`);
1451
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
1452
+ if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
1453
+ // eslint-disable-next-line no-console
1454
+ console.log(`InstanceCache: destroyed record for ${String(identifier)}`);
1455
+ }
1339
1456
  }
1340
1457
  }
1341
1458
  if (cache) {
1342
1459
  cache.unloadRecord(identifier);
1343
1460
  removeRecordDataFor(identifier);
1344
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
1345
- // eslint-disable-next-line no-console
1346
- console.log(`InstanceCache: destroyed cache for ${String(identifier)}`);
1461
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
1462
+ if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
1463
+ // eslint-disable-next-line no-console
1464
+ console.log(`InstanceCache: destroyed cache for ${String(identifier)}`);
1465
+ }
1347
1466
  }
1348
1467
  } else {
1349
1468
  this.disconnect(identifier);
1350
1469
  }
1351
1470
  this.store._requestCache._clearEntries(identifier);
1352
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
1353
- // eslint-disable-next-line no-console
1354
- console.log(`InstanceCache: unloaded RecordData for ${String(identifier)}`);
1355
- // eslint-disable-next-line no-console
1356
- console.groupEnd();
1471
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
1472
+ if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
1473
+ // eslint-disable-next-line no-console
1474
+ console.log(`InstanceCache: unloaded RecordData for ${String(identifier)}`);
1475
+ // eslint-disable-next-line no-console
1476
+ console.groupEnd();
1477
+ }
1357
1478
  }
1358
1479
  });
1359
1480
  }
@@ -1408,9 +1529,11 @@ class InstanceCache {
1408
1529
  warn(`Your ${type} record was saved to the server, but the response does not have an id.`, !(oldId !== null && id === null));
1409
1530
  return;
1410
1531
  }
1411
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE)) {
1412
- // eslint-disable-next-line no-console
1413
- console.log(`InstanceCache: updating id to '${id}' for record ${String(identifier)}`);
1532
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_INSTANCE_CACHE)) {
1533
+ if (getGlobalConfig().WarpDrive.debug.LOG_INSTANCE_CACHE || globalThis.getWarpDriveRuntimeConfig().debug.LOG_INSTANCE_CACHE) {
1534
+ // eslint-disable-next-line no-console
1535
+ console.log(`InstanceCache: updating id to '${id}' for record ${String(identifier)}`);
1536
+ }
1414
1537
  }
1415
1538
  const existingIdentifier = this.store.identifierCache.peekRecordIdentifier({
1416
1539
  type,
@@ -1727,7 +1850,9 @@ class CacheManager {
1727
1850
  peek(identifier) {
1728
1851
  return this.#cache.peek(identifier);
1729
1852
  }
1730
-
1853
+ peekRemoteState(identifier) {
1854
+ return this.#cache.peekRemoteState(identifier);
1855
+ }
1731
1856
  /**
1732
1857
  * Peek the Cache for the existing request data associated with
1733
1858
  * a cacheable request
@@ -1950,6 +2075,19 @@ class CacheManager {
1950
2075
  return this.#cache.getAttr(identifier, propertyName);
1951
2076
  }
1952
2077
 
2078
+ /**
2079
+ * Retrieve the remote state for an attribute from the cache
2080
+ *
2081
+ * @method getRemoteAttr
2082
+ * @public
2083
+ * @param identifier
2084
+ * @param propertyName
2085
+ * @return {unknown}
2086
+ */
2087
+ getRemoteAttr(identifier, propertyName) {
2088
+ return this.#cache.getRemoteAttr(identifier, propertyName);
2089
+ }
2090
+
1953
2091
  /**
1954
2092
  * Mutate the data for an attribute in the cache
1955
2093
  *
@@ -2074,6 +2212,19 @@ class CacheManager {
2074
2212
  return this.#cache.getRelationship(identifier, propertyName);
2075
2213
  }
2076
2214
 
2215
+ /**
2216
+ * Query the cache for the remote state of a relationship property
2217
+ *
2218
+ * @method getRelationship
2219
+ * @public
2220
+ * @param identifier
2221
+ * @param propertyName
2222
+ * @return resource relationship object
2223
+ */
2224
+ getRemoteRelationship(identifier, propertyName) {
2225
+ return this.#cache.getRemoteRelationship(identifier, propertyName);
2226
+ }
2227
+
2077
2228
  // Resource State
2078
2229
  // ===============
2079
2230
 
@@ -2158,27 +2309,51 @@ class CacheManager {
2158
2309
  * @module @ember-data/store
2159
2310
  */
2160
2311
 
2161
- let tokenId = 0;
2162
- const CacheOperations = new Set(['added', 'removed', 'state', 'updated', 'invalidated']);
2163
2312
  function isCacheOperationValue(value) {
2164
- return CacheOperations.has(value);
2313
+ return value === 'added' || value === 'state' || value === 'updated' || value === 'removed' || value === 'invalidated';
2165
2314
  }
2166
2315
  function runLoopIsFlushing() {
2167
2316
  //@ts-expect-error
2168
2317
  return !!_backburner.currentInstance && _backburner._autorun !== true;
2169
2318
  }
2170
- function _unsubscribe(tokens, token, cache) {
2171
- const identifier = tokens.get(token);
2172
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS)) {
2173
- if (!identifier) {
2174
- // eslint-disable-next-line no-console
2175
- console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
2319
+ function count(label) {
2320
+ // @ts-expect-error
2321
+ // eslint-disable-next-line
2322
+ globalThis.__WarpDriveMetricCountData[label] = (globalThis.__WarpDriveMetricCountData[label] || 0) + 1;
2323
+ }
2324
+ function asInternalToken(token) {
2325
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2326
+ if (!test) {
2327
+ throw new Error(`Expected a token with a 'for' property`);
2328
+ }
2329
+ })(token && typeof token === 'function' && 'for' in token) : {};
2330
+ }
2331
+ function _unsubscribe(token, cache) {
2332
+ asInternalToken(token);
2333
+ const identifier = token.for;
2334
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
2335
+ if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
2336
+ if (!identifier) {
2337
+ // eslint-disable-next-line no-console
2338
+ console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
2339
+ }
2176
2340
  }
2177
2341
  }
2178
2342
  if (identifier) {
2179
- tokens.delete(token);
2180
- const map = cache.get(identifier);
2181
- map?.delete(token);
2343
+ const callbacks = cache.get(identifier);
2344
+ if (!callbacks) {
2345
+ return;
2346
+ }
2347
+ const index = callbacks.indexOf(token);
2348
+ if (index === -1) {
2349
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2350
+ if (!test) {
2351
+ throw new Error(`Cannot unsubscribe a token that is not subscribed`);
2352
+ }
2353
+ })(index !== -1) : {};
2354
+ return;
2355
+ }
2356
+ callbacks.splice(index, 1);
2182
2357
  }
2183
2358
  }
2184
2359
 
@@ -2199,7 +2374,6 @@ class NotificationManager {
2199
2374
  this._buffered = new Map();
2200
2375
  this._hasFlush = false;
2201
2376
  this._cache = new Map();
2202
- this._tokens = new Map();
2203
2377
  }
2204
2378
 
2205
2379
  /**
@@ -2236,17 +2410,26 @@ class NotificationManager {
2236
2410
  throw new Error(`Expected to receive a stable Identifier to subscribe to`);
2237
2411
  }
2238
2412
  })(identifier === 'resource' || identifier === 'document' || isStableIdentifier(identifier) || isDocumentIdentifier(identifier)) : {};
2239
- let map = this._cache.get(identifier);
2240
- if (!map) {
2241
- map = new Map();
2242
- this._cache.set(identifier, map);
2413
+ let callbacks = this._cache.get(identifier);
2414
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2415
+ if (!test) {
2416
+ throw new Error(`expected to receive a valid callback`);
2417
+ }
2418
+ })(typeof callback === 'function') : {};
2419
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2420
+ if (!test) {
2421
+ throw new Error(`cannot subscribe with the same callback twice`);
2422
+ }
2423
+ })(!callbacks || !callbacks.includes(callback)) : {};
2424
+ // we use the callback as the cancellation token
2425
+ //@ts-expect-error
2426
+ callback.for = identifier;
2427
+ if (!callbacks) {
2428
+ callbacks = [];
2429
+ this._cache.set(identifier, callbacks);
2243
2430
  }
2244
- const unsubToken = macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? {
2245
- _tokenRef: tokenId++
2246
- } : {};
2247
- map.set(unsubToken, callback);
2248
- this._tokens.set(unsubToken, identifier);
2249
- return unsubToken;
2431
+ callbacks.push(callback);
2432
+ return callback;
2250
2433
  }
2251
2434
 
2252
2435
  /**
@@ -2258,7 +2441,7 @@ class NotificationManager {
2258
2441
  */
2259
2442
  unsubscribe(token) {
2260
2443
  if (!this.isDestroyed) {
2261
- _unsubscribe(this._tokens, token, this._cache);
2444
+ _unsubscribe(token, this._cache);
2262
2445
  }
2263
2446
  }
2264
2447
 
@@ -2280,17 +2463,15 @@ class NotificationManager {
2280
2463
  }
2281
2464
  })(!key || value === 'attributes' || value === 'relationships') : {};
2282
2465
  if (!isStableIdentifier(identifier) && !isDocumentIdentifier(identifier)) {
2283
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS)) {
2284
- // eslint-disable-next-line no-console
2285
- console.log(`Notifying: Expected to receive a stable Identifier to notify '${value}' '${key || ''}' with, but ${String(identifier)} is not in the cache`, identifier);
2466
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
2467
+ if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
2468
+ // eslint-disable-next-line no-console
2469
+ console.log(`Notifying: Expected to receive a stable Identifier to notify '${value}' '${key || ''}' with, but ${String(identifier)} is not in the cache`, identifier);
2470
+ }
2286
2471
  }
2287
2472
  return false;
2288
2473
  }
2289
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS)) {
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);
2474
+ const hasSubscribers = Boolean(this._cache.get(identifier)?.length);
2294
2475
  if (isCacheOperationValue(value) || hasSubscribers) {
2295
2476
  let buffer = this._buffered.get(identifier);
2296
2477
  if (!buffer) {
@@ -2298,7 +2479,29 @@ class NotificationManager {
2298
2479
  this._buffered.set(identifier, buffer);
2299
2480
  }
2300
2481
  buffer.push([value, key]);
2301
- this._scheduleNotify();
2482
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
2483
+ if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
2484
+ count(`notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
2485
+ }
2486
+ }
2487
+ if (!this._scheduleNotify()) {
2488
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
2489
+ if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
2490
+ log('notify', 'buffered', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
2491
+ }
2492
+ }
2493
+ }
2494
+ } else {
2495
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
2496
+ if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
2497
+ log('notify', 'discarded', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
2498
+ }
2499
+ }
2500
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
2501
+ if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
2502
+ count(`DISCARDED notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
2503
+ }
2504
+ }
2302
2505
  }
2303
2506
  return hasSubscribers;
2304
2507
  }
@@ -2309,14 +2512,15 @@ class NotificationManager {
2309
2512
  const asyncFlush = this.store._enableAsyncFlush;
2310
2513
  if (this._hasFlush) {
2311
2514
  if (asyncFlush !== false && !runLoopIsFlushing()) {
2312
- return;
2515
+ return false;
2313
2516
  }
2314
2517
  }
2315
2518
  if (asyncFlush && !runLoopIsFlushing()) {
2316
2519
  this._hasFlush = true;
2317
- return;
2520
+ return false;
2318
2521
  }
2319
2522
  this._flush();
2523
+ return true;
2320
2524
  }
2321
2525
  _flush() {
2322
2526
  const buffered = this._buffered;
@@ -2334,9 +2538,10 @@ class NotificationManager {
2334
2538
  this._onFlushCB = undefined;
2335
2539
  }
2336
2540
  _flushNotification(identifier, value, key) {
2337
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS)) {
2338
- // eslint-disable-next-line no-console
2339
- console.log(`Notifying: ${String(identifier)}\t${value}\t${key || ''}`);
2541
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
2542
+ if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
2543
+ log('notify', '', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
2544
+ }
2340
2545
  }
2341
2546
 
2342
2547
  // TODO for documents this will need to switch based on Identifier kind
@@ -2348,11 +2553,11 @@ class NotificationManager {
2348
2553
  });
2349
2554
  }
2350
2555
  }
2351
- const callbackMap = this._cache.get(identifier);
2352
- if (!callbackMap || !callbackMap.size) {
2556
+ const callbacks = this._cache.get(identifier);
2557
+ if (!callbacks || !callbacks.length) {
2353
2558
  return false;
2354
2559
  }
2355
- callbackMap.forEach(cb => {
2560
+ callbacks.forEach(cb => {
2356
2561
  // @ts-expect-error overload doesn't narrow within body
2357
2562
  cb(identifier, value, key);
2358
2563
  });
@@ -2360,7 +2565,6 @@ class NotificationManager {
2360
2565
  }
2361
2566
  destroy() {
2362
2567
  this.isDestroyed = true;
2363
- this._tokens.clear();
2364
2568
  this._cache.clear();
2365
2569
  }
2366
2570
  }
@@ -2682,7 +2886,7 @@ class IdentifierArray {
2682
2886
  return false;
2683
2887
  }
2684
2888
  const original = target[index];
2685
- const newIdentifier = extractIdentifierFromRecord$1(value);
2889
+ const newIdentifier = extractIdentifierFromRecord$2(value);
2686
2890
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2687
2891
  if (!test) {
2688
2892
  throw new Error(`Expected a record`);
@@ -2723,9 +2927,18 @@ class IdentifierArray {
2723
2927
  return Reflect.deleteProperty(target, prop);
2724
2928
  },
2725
2929
  getPrototypeOf() {
2726
- return IdentifierArray.prototype;
2930
+ return Array.prototype;
2727
2931
  }
2728
2932
  });
2933
+ if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
2934
+ Object.defineProperty(this, '__SHOW_ME_THE_DATA_(debug mode only)__', {
2935
+ enumerable: false,
2936
+ configurable: true,
2937
+ get() {
2938
+ return proxy.slice();
2939
+ }
2940
+ });
2941
+ }
2729
2942
  createArrayTags(proxy, _SIGNAL);
2730
2943
  this[NOTIFY] = this[NOTIFY].bind(proxy);
2731
2944
  return proxy;
@@ -2866,7 +3079,7 @@ Collection.prototype.query = null;
2866
3079
  // Ensure instanceof works correctly
2867
3080
  // Object.setPrototypeOf(IdentifierArray.prototype, Array.prototype);
2868
3081
 
2869
- function assertRecordPassedToHasMany(record) {
3082
+ function assertRecordPassedToHasMany$1(record) {
2870
3083
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
2871
3084
  if (!test) {
2872
3085
  throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed $${typeof record}`);
@@ -2880,11 +3093,11 @@ function assertRecordPassedToHasMany(record) {
2880
3093
  }
2881
3094
  }()) : {};
2882
3095
  }
2883
- function extractIdentifierFromRecord$1(record) {
3096
+ function extractIdentifierFromRecord$2(record) {
2884
3097
  if (!record) {
2885
3098
  return null;
2886
3099
  }
2887
- assertRecordPassedToHasMany(record);
3100
+ assertRecordPassedToHasMany$1(record);
2888
3101
  return recordIdentifierFor(record);
2889
3102
  }
2890
3103
 
@@ -2979,6 +3192,9 @@ class RecordArrayManager {
2979
3192
  sync(array, pending, this._set.get(array));
2980
3193
  this._pending.delete(array);
2981
3194
  }
3195
+ mutate(mutation) {
3196
+ this.store.cache.mutate(mutation);
3197
+ }
2982
3198
 
2983
3199
  /**
2984
3200
  Get the `RecordArray` for a modelName, which contains all loaded records of
@@ -3495,6 +3711,118 @@ function constructResource(type, id, lid) {
3495
3711
  */
3496
3712
  // this import location is deprecated but breaks in 4.8 and older
3497
3713
 
3714
+ // @ts-expect-error adding to globalThis
3715
+ globalThis.setWarpDriveLogging = setLogging;
3716
+
3717
+ // @ts-expect-error adding to globalThis
3718
+ globalThis.getWarpDriveRuntimeConfig = getRuntimeConfig;
3719
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
3720
+ if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
3721
+ // @ts-expect-error adding to globalThis
3722
+ // eslint-disable-next-line
3723
+ globalThis.__WarpDriveMetricCountData = globalThis.__WarpDriveMetricCountData || {};
3724
+
3725
+ // @ts-expect-error adding to globalThis
3726
+ globalThis.getWarpDriveMetricCounts = () => {
3727
+ // @ts-expect-error
3728
+ // eslint-disable-next-line
3729
+ return structuredClone(globalThis.__WarpDriveMetricCountData);
3730
+ };
3731
+
3732
+ // @ts-expect-error adding to globalThis
3733
+ globalThis.resetWarpDriveMetricCounts = () => {
3734
+ // @ts-expect-error
3735
+ globalThis.__WarpDriveMetricCountData = {};
3736
+ };
3737
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS)) {
3738
+ if (getGlobalConfig().WarpDrive.debug.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.__INTERNAL_LOG_NATIVE_MAP_SET_COUNTS) {
3739
+ // @ts-expect-error adding to globalThis
3740
+ globalThis.__primitiveInstanceId = 0;
3741
+ function interceptAndLog(klassName, methodName) {
3742
+ const klass = globalThis[klassName];
3743
+ if (methodName === 'constructor') {
3744
+ const instantiationLabel = `new ${klassName}()`;
3745
+ // @ts-expect-error
3746
+ globalThis[klassName] = class extends klass {
3747
+ // @ts-expect-error
3748
+ constructor(...args) {
3749
+ // eslint-disable-next-line
3750
+ super(...args);
3751
+ // @ts-expect-error
3752
+
3753
+ const instanceId = globalThis.__primitiveInstanceId++;
3754
+ // @ts-expect-error
3755
+ // eslint-disable-next-line
3756
+ globalThis.__WarpDriveMetricCountData[instantiationLabel] =
3757
+ // @ts-expect-error
3758
+ // eslint-disable-next-line
3759
+ (globalThis.__WarpDriveMetricCountData[instantiationLabel] || 0) + 1;
3760
+ // @ts-expect-error
3761
+ this.instanceName = `${klassName}:${instanceId} - ${new Error().stack?.split('\n')[2]}`;
3762
+ }
3763
+ };
3764
+ } else {
3765
+ // @ts-expect-error
3766
+ // eslint-disable-next-line
3767
+ const original = klass.prototype[methodName];
3768
+ const logName = `${klassName}.${methodName}`;
3769
+
3770
+ // @ts-expect-error
3771
+ klass.prototype[methodName] = function (...args) {
3772
+ // @ts-expect-error
3773
+ // eslint-disable-next-line
3774
+ globalThis.__WarpDriveMetricCountData[logName] = (globalThis.__WarpDriveMetricCountData[logName] || 0) + 1;
3775
+ // @ts-expect-error
3776
+ const {
3777
+ instanceName
3778
+ } = this;
3779
+ if (!instanceName) {
3780
+ // @ts-expect-error
3781
+ const instanceId = globalThis.__primitiveInstanceId++;
3782
+ // @ts-expect-error
3783
+ this.instanceName = `${klassName}.${methodName}:${instanceId} - ${new Error().stack?.split('\n')[2]}`;
3784
+ }
3785
+ const instanceLogName = `${logName} (${instanceName})`;
3786
+ // @ts-expect-error
3787
+ // eslint-disable-next-line
3788
+ globalThis.__WarpDriveMetricCountData[instanceLogName] =
3789
+ // @ts-expect-error
3790
+ // eslint-disable-next-line
3791
+ (globalThis.__WarpDriveMetricCountData[instanceLogName] || 0) + 1;
3792
+ // eslint-disable-next-line
3793
+ return original.apply(this, args);
3794
+ };
3795
+ }
3796
+ }
3797
+ interceptAndLog('Set', 'constructor');
3798
+ interceptAndLog('Set', 'add');
3799
+ interceptAndLog('Set', 'delete');
3800
+ interceptAndLog('Set', 'has');
3801
+ interceptAndLog('Set', 'set');
3802
+ interceptAndLog('Set', 'get');
3803
+ interceptAndLog('Map', 'constructor');
3804
+ interceptAndLog('Map', 'set');
3805
+ interceptAndLog('Map', 'delete');
3806
+ interceptAndLog('Map', 'has');
3807
+ interceptAndLog('Map', 'add');
3808
+ interceptAndLog('Map', 'get');
3809
+ interceptAndLog('WeakSet', 'constructor');
3810
+ interceptAndLog('WeakSet', 'add');
3811
+ interceptAndLog('WeakSet', 'delete');
3812
+ interceptAndLog('WeakSet', 'has');
3813
+ interceptAndLog('WeakSet', 'set');
3814
+ interceptAndLog('WeakSet', 'get');
3815
+ interceptAndLog('WeakMap', 'constructor');
3816
+ interceptAndLog('WeakMap', 'set');
3817
+ interceptAndLog('WeakMap', 'delete');
3818
+ interceptAndLog('WeakMap', 'has');
3819
+ interceptAndLog('WeakMap', 'add');
3820
+ interceptAndLog('WeakMap', 'get');
3821
+ }
3822
+ }
3823
+ }
3824
+ }
3825
+
3498
3826
  // `AwaitedKeys` is needed here to resolve any promise types like `PromiseBelongsTo`.
3499
3827
 
3500
3828
  /**
@@ -3622,12 +3950,9 @@ class Store extends BaseClass {
3622
3950
  * import Fetch from '@ember-data/request/fetch';
3623
3951
  *
3624
3952
  * class extends Store {
3625
- * constructor() {
3626
- * super(...arguments);
3627
- * this.requestManager = new RequestManager();
3628
- * this.requestManager.use([Fetch]);
3629
- * this.requestManager.useCache(CacheHandler);
3630
- * }
3953
+ * requestManager = new RequestManager()
3954
+ * .use([Fetch])
3955
+ * .useCache(CacheHandler);
3631
3956
  * }
3632
3957
  * ```
3633
3958
  *
@@ -3869,7 +4194,7 @@ class Store extends BaseClass {
3869
4194
  // the user has had the chance to set the prop.
3870
4195
  const opts = {
3871
4196
  store: this,
3872
- [EnableHydration]: true
4197
+ [EnableHydration]: requestConfig[EnableHydration] ?? true
3873
4198
  };
3874
4199
  if (requestConfig.records) {
3875
4200
  const identifierCache = this.identifierCache;
@@ -3880,22 +4205,26 @@ class Store extends BaseClass {
3880
4205
  opts.disableTestWaiter = typeof requestConfig.disableTestWaiter === 'boolean' ? requestConfig.disableTestWaiter : true;
3881
4206
  }
3882
4207
  }
3883
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_REQUESTS)) {
3884
- let options;
3885
- try {
3886
- options = JSON.parse(JSON.stringify(requestConfig));
3887
- } catch {
3888
- options = requestConfig;
4208
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_REQUESTS)) {
4209
+ if (getGlobalConfig().WarpDrive.debug.LOG_REQUESTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_REQUESTS) {
4210
+ let options;
4211
+ try {
4212
+ options = JSON.parse(JSON.stringify(requestConfig));
4213
+ } catch {
4214
+ options = requestConfig;
4215
+ }
4216
+ // eslint-disable-next-line no-console
4217
+ console.log(`request: [[START]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`, options);
3889
4218
  }
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
4219
  }
3893
4220
  const request = Object.assign({}, requestConfig, opts);
3894
4221
  const future = this.requestManager.request(request);
3895
4222
  future.onFinalize(() => {
3896
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_REQUESTS)) {
3897
- // eslint-disable-next-line no-console
3898
- console.log(`request: [[FINALIZE]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`);
4223
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_REQUESTS)) {
4224
+ if (getGlobalConfig().WarpDrive.debug.LOG_REQUESTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_REQUESTS) {
4225
+ // eslint-disable-next-line no-console
4226
+ console.log(`request: [[FINALIZE]] ${requestConfig.op && !requestConfig.url ? '(LEGACY) ' : ''}${requestConfig.op || '<unknown operation>'} ${requestConfig.url || '<empty url>'} ${requestConfig.method || '<empty method>'}`);
4227
+ }
3899
4228
  }
3900
4229
  // skip flush for legacy belongsTo
3901
4230
  if (requestConfig.op === 'findBelongsTo' && !requestConfig.url) {
@@ -4101,9 +4430,8 @@ class Store extends BaseClass {
4101
4430
  This will cause the record to be destroyed and freed up for garbage collection.
4102
4431
  Example
4103
4432
  ```javascript
4104
- store.findRecord('post', '1').then(function(post) {
4105
- store.unloadRecord(post);
4106
- });
4433
+ const { content: { data: post } } = await store.request(findRecord({ type: 'post', id: '1' }));
4434
+ store.unloadRecord(post);
4107
4435
  ```
4108
4436
  @method unloadRecord
4109
4437
  @public
@@ -5155,14 +5483,16 @@ class Store extends BaseClass {
5155
5483
  if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
5156
5484
  assertDestroyingStore(this, '_push');
5157
5485
  }
5158
- if (macroCondition(getGlobalConfig().WarpDrive.debug.LOG_PAYLOADS)) {
5159
- try {
5160
- const data = JSON.parse(JSON.stringify(jsonApiDoc));
5161
- // eslint-disable-next-line no-console
5162
- console.log('EmberData | Payload - push', data);
5163
- } catch {
5164
- // eslint-disable-next-line no-console
5165
- console.log('EmberData | Payload - push', jsonApiDoc);
5486
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_PAYLOADS)) {
5487
+ if (getGlobalConfig().WarpDrive.debug.LOG_PAYLOADS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_PAYLOADS) {
5488
+ try {
5489
+ const data = JSON.parse(JSON.stringify(jsonApiDoc));
5490
+ // eslint-disable-next-line no-console
5491
+ console.log('EmberData | Payload - push', data);
5492
+ } catch {
5493
+ // eslint-disable-next-line no-console
5494
+ console.log('EmberData | Payload - push', jsonApiDoc);
5495
+ }
5166
5496
  }
5167
5497
  }
5168
5498
  if (asyncFlush) {
@@ -5385,9 +5715,9 @@ function normalizeProperties(store, identifier, properties) {
5385
5715
  if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
5386
5716
  assertRecordsPassedToHasMany(properties[prop]);
5387
5717
  }
5388
- properties[prop] = extractIdentifiersFromRecords(properties[prop]);
5718
+ properties[prop] = extractIdentifiersFromRecords$1(properties[prop]);
5389
5719
  } else if (field.kind === 'belongsTo') {
5390
- properties[prop] = extractIdentifierFromRecord(properties[prop]);
5720
+ properties[prop] = extractIdentifierFromRecord$1(properties[prop]);
5391
5721
  }
5392
5722
  }
5393
5723
  }
@@ -5415,10 +5745,10 @@ function assertRecordsPassedToHasMany(records) {
5415
5745
  });
5416
5746
  }()) : {};
5417
5747
  }
5418
- function extractIdentifiersFromRecords(records) {
5419
- return records.map(record => extractIdentifierFromRecord(record));
5748
+ function extractIdentifiersFromRecords$1(records) {
5749
+ return records.map(record => extractIdentifierFromRecord$1(record));
5420
5750
  }
5421
- function extractIdentifierFromRecord(recordOrPromiseRecord) {
5751
+ function extractIdentifierFromRecord$1(recordOrPromiseRecord) {
5422
5752
  if (!recordOrPromiseRecord) {
5423
5753
  return null;
5424
5754
  }
@@ -6066,4 +6396,475 @@ function fetchContentAndHydrate(next, context, identifier, priority) {
6066
6396
  }]
6067
6397
  });
6068
6398
  }
6069
- 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 };
6399
+
6400
+ /**
6401
+ @module @ember-data/store
6402
+ */
6403
+ /**
6404
+ A `ManyArray` is a `MutableArray` that represents the contents of a has-many
6405
+ relationship.
6406
+
6407
+ The `ManyArray` is instantiated lazily the first time the relationship is
6408
+ requested.
6409
+
6410
+ This class is not intended to be directly instantiated by consuming applications.
6411
+
6412
+ ### Inverses
6413
+
6414
+ Often, the relationships in Ember Data applications will have
6415
+ an inverse. For example, imagine the following models are
6416
+ defined:
6417
+
6418
+ ```app/models/post.js
6419
+ import Model, { hasMany } from '@ember-data/model';
6420
+
6421
+ export default class PostModel extends Model {
6422
+ @hasMany('comment') comments;
6423
+ }
6424
+ ```
6425
+
6426
+ ```app/models/comment.js
6427
+ import Model, { belongsTo } from '@ember-data/model';
6428
+
6429
+ export default class CommentModel extends Model {
6430
+ @belongsTo('post') post;
6431
+ }
6432
+ ```
6433
+
6434
+ If you created a new instance of `Post` and added
6435
+ a `Comment` record to its `comments` has-many
6436
+ relationship, you would expect the comment's `post`
6437
+ property to be set to the post that contained
6438
+ the has-many.
6439
+
6440
+ We call the record to which a relationship belongs-to the
6441
+ relationship's _owner_.
6442
+
6443
+ @class ManyArray
6444
+ @public
6445
+ */
6446
+ class RelatedCollection extends IdentifierArray {
6447
+ /**
6448
+ The loading state of this array
6449
+ @property {Boolean} isLoaded
6450
+ @public
6451
+ */
6452
+
6453
+ /**
6454
+ `true` if the relationship is polymorphic, `false` otherwise.
6455
+ @property {Boolean} isPolymorphic
6456
+ @private
6457
+ */
6458
+
6459
+ /**
6460
+ Metadata associated with the request for async hasMany relationships.
6461
+ Example
6462
+ Given that the server returns the following JSON payload when fetching a
6463
+ hasMany relationship:
6464
+ ```js
6465
+ {
6466
+ "comments": [{
6467
+ "id": 1,
6468
+ "comment": "This is the first comment",
6469
+ }, {
6470
+ // ...
6471
+ }],
6472
+ "meta": {
6473
+ "page": 1,
6474
+ "total": 5
6475
+ }
6476
+ }
6477
+ ```
6478
+ You can then access the meta data via the `meta` property:
6479
+ ```js
6480
+ let comments = await post.comments;
6481
+ let meta = comments.meta;
6482
+ // meta.page => 1
6483
+ // meta.total => 5
6484
+ ```
6485
+ @property {Object | null} meta
6486
+ @public
6487
+ */
6488
+
6489
+ /**
6490
+ * Retrieve the links for this relationship
6491
+ *
6492
+ @property {Object | null} links
6493
+ @public
6494
+ */
6495
+
6496
+ constructor(options) {
6497
+ super(options);
6498
+ this.isLoaded = options.isLoaded || false;
6499
+ this.isAsync = options.isAsync || false;
6500
+ this.isPolymorphic = options.isPolymorphic || false;
6501
+ this.identifier = options.identifier;
6502
+ this.key = options.key;
6503
+ }
6504
+ [MUTATE](target, receiver, prop, args, _SIGNAL) {
6505
+ switch (prop) {
6506
+ case 'length 0':
6507
+ {
6508
+ Reflect.set(target, 'length', 0);
6509
+ mutateReplaceRelatedRecords(this, [], _SIGNAL);
6510
+ return true;
6511
+ }
6512
+ case 'replace cell':
6513
+ {
6514
+ const [index, prior, value] = args;
6515
+ target[index] = value;
6516
+ mutateReplaceRelatedRecord(this, {
6517
+ value,
6518
+ prior,
6519
+ index
6520
+ }, _SIGNAL);
6521
+ return true;
6522
+ }
6523
+ case 'push':
6524
+ {
6525
+ const newValues = extractIdentifiersFromRecords(args);
6526
+ assertNoDuplicates(this, target, currentState => currentState.push(...newValues), `Cannot push duplicates to a hasMany's state.`);
6527
+ if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
6528
+ // dedupe
6529
+ const seen = new Set(target);
6530
+ const unique = new Set();
6531
+ args.forEach(item => {
6532
+ const identifier = recordIdentifierFor(item);
6533
+ if (!seen.has(identifier)) {
6534
+ seen.add(identifier);
6535
+ unique.add(item);
6536
+ }
6537
+ });
6538
+ const newArgs = Array.from(unique);
6539
+ const result = Reflect.apply(target[prop], receiver, newArgs);
6540
+ if (newArgs.length) {
6541
+ mutateAddToRelatedRecords(this, {
6542
+ value: extractIdentifiersFromRecords(newArgs)
6543
+ }, _SIGNAL);
6544
+ }
6545
+ return result;
6546
+ }
6547
+
6548
+ // else, no dedupe, error on duplicates
6549
+ const result = Reflect.apply(target[prop], receiver, args);
6550
+ if (newValues.length) {
6551
+ mutateAddToRelatedRecords(this, {
6552
+ value: newValues
6553
+ }, _SIGNAL);
6554
+ }
6555
+ return result;
6556
+ }
6557
+ case 'pop':
6558
+ {
6559
+ const result = Reflect.apply(target[prop], receiver, args);
6560
+ if (result) {
6561
+ mutateRemoveFromRelatedRecords(this, {
6562
+ value: recordIdentifierFor(result)
6563
+ }, _SIGNAL);
6564
+ }
6565
+ return result;
6566
+ }
6567
+ case 'unshift':
6568
+ {
6569
+ const newValues = extractIdentifiersFromRecords(args);
6570
+ assertNoDuplicates(this, target, currentState => currentState.unshift(...newValues), `Cannot unshift duplicates to a hasMany's state.`);
6571
+ if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
6572
+ // dedupe
6573
+ const seen = new Set(target);
6574
+ const unique = new Set();
6575
+ args.forEach(item => {
6576
+ const identifier = recordIdentifierFor(item);
6577
+ if (!seen.has(identifier)) {
6578
+ seen.add(identifier);
6579
+ unique.add(item);
6580
+ }
6581
+ });
6582
+ const newArgs = Array.from(unique);
6583
+ const result = Reflect.apply(target[prop], receiver, newArgs);
6584
+ if (newArgs.length) {
6585
+ mutateAddToRelatedRecords(this, {
6586
+ value: extractIdentifiersFromRecords(newArgs),
6587
+ index: 0
6588
+ }, _SIGNAL);
6589
+ }
6590
+ return result;
6591
+ }
6592
+
6593
+ // else, no dedupe, error on duplicates
6594
+ const result = Reflect.apply(target[prop], receiver, args);
6595
+ if (newValues.length) {
6596
+ mutateAddToRelatedRecords(this, {
6597
+ value: newValues,
6598
+ index: 0
6599
+ }, _SIGNAL);
6600
+ }
6601
+ return result;
6602
+ }
6603
+ case 'shift':
6604
+ {
6605
+ const result = Reflect.apply(target[prop], receiver, args);
6606
+ if (result) {
6607
+ mutateRemoveFromRelatedRecords(this, {
6608
+ value: recordIdentifierFor(result),
6609
+ index: 0
6610
+ }, _SIGNAL);
6611
+ }
6612
+ return result;
6613
+ }
6614
+ case 'sort':
6615
+ {
6616
+ const result = Reflect.apply(target[prop], receiver, args);
6617
+ mutateSortRelatedRecords(this, result.map(recordIdentifierFor), _SIGNAL);
6618
+ return result;
6619
+ }
6620
+ case 'splice':
6621
+ {
6622
+ const [start, deleteCount, ...adds] = args;
6623
+
6624
+ // detect a full replace
6625
+ if (start === 0 && deleteCount === this[SOURCE].length) {
6626
+ const newValues = extractIdentifiersFromRecords(adds);
6627
+ assertNoDuplicates(this, target, currentState => currentState.splice(start, deleteCount, ...newValues), `Cannot replace a hasMany's state with a new state that contains duplicates.`);
6628
+ if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
6629
+ // dedupe
6630
+ const current = new Set(adds);
6631
+ const unique = Array.from(current);
6632
+ const newArgs = [start, deleteCount].concat(unique);
6633
+ const result = Reflect.apply(target[prop], receiver, newArgs);
6634
+ mutateReplaceRelatedRecords(this, extractIdentifiersFromRecords(unique), _SIGNAL);
6635
+ return result;
6636
+ }
6637
+
6638
+ // else, no dedupe, error on duplicates
6639
+ const result = Reflect.apply(target[prop], receiver, args);
6640
+ mutateReplaceRelatedRecords(this, newValues, _SIGNAL);
6641
+ return result;
6642
+ }
6643
+ const newValues = extractIdentifiersFromRecords(adds);
6644
+ assertNoDuplicates(this, target, currentState => currentState.splice(start, deleteCount, ...newValues), `Cannot splice a hasMany's state with a new state that contains duplicates.`);
6645
+ if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
6646
+ // dedupe
6647
+ const currentState = target.slice();
6648
+ currentState.splice(start, deleteCount);
6649
+ const seen = new Set(currentState);
6650
+ const unique = [];
6651
+ adds.forEach(item => {
6652
+ const identifier = recordIdentifierFor(item);
6653
+ if (!seen.has(identifier)) {
6654
+ seen.add(identifier);
6655
+ unique.push(item);
6656
+ }
6657
+ });
6658
+ const newArgs = [start, deleteCount, ...unique];
6659
+ const result = Reflect.apply(target[prop], receiver, newArgs);
6660
+ if (deleteCount > 0) {
6661
+ mutateRemoveFromRelatedRecords(this, {
6662
+ value: result.map(recordIdentifierFor),
6663
+ index: start
6664
+ }, _SIGNAL);
6665
+ }
6666
+ if (unique.length > 0) {
6667
+ mutateAddToRelatedRecords(this, {
6668
+ value: extractIdentifiersFromRecords(unique),
6669
+ index: start
6670
+ }, _SIGNAL);
6671
+ }
6672
+ return result;
6673
+ }
6674
+
6675
+ // else, no dedupe, error on duplicates
6676
+ const result = Reflect.apply(target[prop], receiver, args);
6677
+ if (deleteCount > 0) {
6678
+ mutateRemoveFromRelatedRecords(this, {
6679
+ value: result.map(recordIdentifierFor),
6680
+ index: start
6681
+ }, _SIGNAL);
6682
+ }
6683
+ if (newValues.length > 0) {
6684
+ mutateAddToRelatedRecords(this, {
6685
+ value: newValues,
6686
+ index: start
6687
+ }, _SIGNAL);
6688
+ }
6689
+ return result;
6690
+ }
6691
+ default:
6692
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6693
+ {
6694
+ throw new Error(`unable to convert ${prop} into a transaction that updates the cache state for this record array`);
6695
+ }
6696
+ })() : {};
6697
+ }
6698
+ }
6699
+ notify() {
6700
+ const signal = this[ARRAY_SIGNAL];
6701
+ signal.shouldReset = true;
6702
+ notifyArray(this);
6703
+ }
6704
+
6705
+ /**
6706
+ Reloads all of the records in the manyArray. If the manyArray
6707
+ holds a relationship that was originally fetched using a links url
6708
+ EmberData will revisit the original links url to repopulate the
6709
+ relationship.
6710
+ If the ManyArray holds the result of a `store.query()` reload will
6711
+ re-run the original query.
6712
+ Example
6713
+ ```javascript
6714
+ let user = store.peekRecord('user', '1')
6715
+ await login(user);
6716
+ let permissions = await user.permissions;
6717
+ await permissions.reload();
6718
+ ```
6719
+ @method reload
6720
+ @public
6721
+ */
6722
+ reload(options) {
6723
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6724
+ if (!test) {
6725
+ throw new Error(`Expected the manager for ManyArray to implement reloadHasMany`);
6726
+ }
6727
+ })(typeof this._manager.reloadHasMany === 'function') : {};
6728
+ // TODO this is odd, we don't ask the store for anything else like this?
6729
+ return this._manager.reloadHasMany(this.key, options);
6730
+ }
6731
+
6732
+ /**
6733
+ Saves all of the records in the `ManyArray`.
6734
+ Note: this API can only be used in legacy mode with a configured Adapter.
6735
+ Example
6736
+ ```javascript
6737
+ const { content: { data: inbox } } = await store.request(findRecord({ type: 'inbox', id: '1' }));
6738
+ let messages = await inbox.messages;
6739
+ messages.forEach((message) => {
6740
+ message.isRead = true;
6741
+ });
6742
+ messages.save();
6743
+ ```
6744
+ @method save
6745
+ @public
6746
+ @return {PromiseArray} promise
6747
+ */
6748
+
6749
+ /**
6750
+ Create a child record within the owner
6751
+ @method createRecord
6752
+ @public
6753
+ @param {Object} hash
6754
+ @return {Model} record
6755
+ */
6756
+ createRecord(hash) {
6757
+ const {
6758
+ store
6759
+ } = this;
6760
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6761
+ if (!test) {
6762
+ throw new Error(`Expected modelName to be set`);
6763
+ }
6764
+ })(this.modelName) : {};
6765
+ const record = store.createRecord(this.modelName, hash);
6766
+ this.push(record);
6767
+ return record;
6768
+ }
6769
+ destroy() {
6770
+ super.destroy(false);
6771
+ }
6772
+ }
6773
+ RelatedCollection.prototype.isAsync = false;
6774
+ RelatedCollection.prototype.isPolymorphic = false;
6775
+ RelatedCollection.prototype.identifier = null;
6776
+ RelatedCollection.prototype.cache = null;
6777
+ RelatedCollection.prototype._inverseIsAsync = false;
6778
+ RelatedCollection.prototype.key = '';
6779
+ RelatedCollection.prototype.DEPRECATED_CLASS_NAME = 'ManyArray';
6780
+ function assertRecordPassedToHasMany(record) {
6781
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6782
+ if (!test) {
6783
+ throw new Error(`All elements of a hasMany relationship must be instances of Model, you passed ${typeof record}`);
6784
+ }
6785
+ })(function () {
6786
+ try {
6787
+ recordIdentifierFor(record);
6788
+ return true;
6789
+ } catch {
6790
+ return false;
6791
+ }
6792
+ }()) : {};
6793
+ }
6794
+ function extractIdentifiersFromRecords(records) {
6795
+ return records.map(extractIdentifierFromRecord);
6796
+ }
6797
+ function extractIdentifierFromRecord(recordOrPromiseRecord) {
6798
+ assertRecordPassedToHasMany(recordOrPromiseRecord);
6799
+ return recordIdentifierFor(recordOrPromiseRecord);
6800
+ }
6801
+ function assertNoDuplicates(collection, target, callback, reason) {
6802
+ const state = target.slice();
6803
+ callback(state);
6804
+ if (state.length !== new Set(state).size) {
6805
+ const duplicates = state.filter((currentValue, currentIndex) => state.indexOf(currentValue) !== currentIndex);
6806
+ if (macroCondition(getGlobalConfig().WarpDrive.deprecations.DEPRECATE_MANY_ARRAY_DUPLICATES)) {
6807
+ 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, {
6808
+ id: 'ember-data:deprecate-many-array-duplicates',
6809
+ for: 'ember-data',
6810
+ until: '6.0',
6811
+ since: {
6812
+ enabled: '5.3',
6813
+ available: '4.13'
6814
+ }
6815
+ });
6816
+ } else {
6817
+ 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- ')}`);
6818
+ }
6819
+ }
6820
+ }
6821
+ function mutateAddToRelatedRecords(collection, operationInfo, _SIGNAL) {
6822
+ mutate(collection, {
6823
+ op: 'addToRelatedRecords',
6824
+ record: collection.identifier,
6825
+ field: collection.key,
6826
+ ...operationInfo
6827
+ }, _SIGNAL);
6828
+ }
6829
+ function mutateRemoveFromRelatedRecords(collection, operationInfo, _SIGNAL) {
6830
+ mutate(collection, {
6831
+ op: 'removeFromRelatedRecords',
6832
+ record: collection.identifier,
6833
+ field: collection.key,
6834
+ ...operationInfo
6835
+ }, _SIGNAL);
6836
+ }
6837
+ function mutateReplaceRelatedRecord(collection, operationInfo, _SIGNAL) {
6838
+ mutate(collection, {
6839
+ op: 'replaceRelatedRecord',
6840
+ record: collection.identifier,
6841
+ field: collection.key,
6842
+ ...operationInfo
6843
+ }, _SIGNAL);
6844
+ }
6845
+ function mutateReplaceRelatedRecords(collection, value, _SIGNAL) {
6846
+ mutate(collection, {
6847
+ op: 'replaceRelatedRecords',
6848
+ record: collection.identifier,
6849
+ field: collection.key,
6850
+ value
6851
+ }, _SIGNAL);
6852
+ }
6853
+ function mutateSortRelatedRecords(collection, value, _SIGNAL) {
6854
+ mutate(collection, {
6855
+ op: 'sortRelatedRecords',
6856
+ record: collection.identifier,
6857
+ field: collection.key,
6858
+ value
6859
+ }, _SIGNAL);
6860
+ }
6861
+ function mutate(collection, mutation, _SIGNAL) {
6862
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6863
+ if (!test) {
6864
+ throw new Error(`Expected the manager for ManyArray to implement mutate`);
6865
+ }
6866
+ })(typeof collection._manager.mutate === 'function') : {};
6867
+ collection._manager.mutate(mutation);
6868
+ addToTransaction(_SIGNAL);
6869
+ }
6870
+ 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 };