@ember-data/store 5.4.0-beta.17 → 5.4.0-beta.19

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 (30) hide show
  1. package/dist/-private.js +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/{many-array-D-iDvWAq.js → many-array-BwVo-2vv.js} +406 -350
  4. package/dist/many-array-BwVo-2vv.js.map +1 -0
  5. package/package.json +21 -21
  6. package/unstable-preview-types/-private/cache-handler/handler.d.ts.map +1 -1
  7. package/unstable-preview-types/-private/cache-handler/utils.d.ts +0 -5
  8. package/unstable-preview-types/-private/cache-handler/utils.d.ts.map +1 -1
  9. package/unstable-preview-types/-private/caches/identifier-cache.d.ts +7 -3
  10. package/unstable-preview-types/-private/caches/identifier-cache.d.ts.map +1 -1
  11. package/unstable-preview-types/-private/caches/instance-cache.d.ts +4 -1
  12. package/unstable-preview-types/-private/caches/instance-cache.d.ts.map +1 -1
  13. package/unstable-preview-types/-private/document.d.ts +23 -14
  14. package/unstable-preview-types/-private/document.d.ts.map +1 -1
  15. package/unstable-preview-types/-private/legacy-model-support/shim-model-class.d.ts +3 -3
  16. package/unstable-preview-types/-private/legacy-model-support/shim-model-class.d.ts.map +1 -1
  17. package/unstable-preview-types/-private/managers/notification-manager.d.ts.map +1 -1
  18. package/unstable-preview-types/-private/managers/record-array-manager.d.ts +7 -5
  19. package/unstable-preview-types/-private/managers/record-array-manager.d.ts.map +1 -1
  20. package/unstable-preview-types/-private/record-arrays/identifier-array.d.ts +3 -1
  21. package/unstable-preview-types/-private/record-arrays/identifier-array.d.ts.map +1 -1
  22. package/unstable-preview-types/-private/store-service.d.ts +1 -3
  23. package/unstable-preview-types/-private/store-service.d.ts.map +1 -1
  24. package/unstable-preview-types/-private.d.ts +2 -2
  25. package/unstable-preview-types/-private.d.ts.map +1 -1
  26. package/unstable-preview-types/-types/q/ds-model.d.ts +3 -3
  27. package/unstable-preview-types/-types/q/ds-model.d.ts.map +1 -1
  28. package/unstable-preview-types/-types/q/schema-service.d.ts +13 -5
  29. package/unstable-preview-types/-types/q/schema-service.d.ts.map +1 -1
  30. package/dist/many-array-D-iDvWAq.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { deprecate, warn } from '@ember/debug';
2
2
  import { macroCondition, getGlobalConfig, dependencySatisfies, importSync } from '@embroider/macros';
3
- import { setLogging, getRuntimeConfig } from '@warp-drive/build-config/runtime';
4
3
  import { EnableHydration, SkipCache } from '@warp-drive/core-types/request';
4
+ import { setLogging, getRuntimeConfig } from '@warp-drive/core-types/runtime';
5
5
  import { getOrSetGlobal, peekTransient, setTransient } from '@warp-drive/core-types/-private';
6
6
  import { _backburner } from '@ember/runloop';
7
- import { defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
7
+ import { defineSubscription, notifySignal, defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB } from '@ember-data/tracking/-private';
8
8
  import { CACHE_OWNER, DEBUG_STALE_CACHE_OWNER, DEBUG_IDENTIFIER_BUCKET, DEBUG_CLIENT_ORIGINATED } from '@warp-drive/core-types/identifier';
9
9
  import { dasherize } from '@ember-data/request-utils/string';
10
10
  import { compat } from '@ember-data/tracking';
@@ -902,6 +902,309 @@ function _log(scope, prefix, subScop1, subScop2, subScop3, subScop4) {
902
902
  return [];
903
903
  }
904
904
 
905
+ /**
906
+ * @module @ember-data/store
907
+ */
908
+ function urlFromLink(link) {
909
+ if (typeof link === 'string') return link;
910
+ return link.href;
911
+ }
912
+
913
+ /**
914
+ * A Document is a class that wraps the response content from a request to the API
915
+ * returned by `Cache.put` or `Cache.peek`, converting resource-identifiers into
916
+ * record instances.
917
+ *
918
+ * It is not directly instantiated by the user, and its properties should not
919
+ * be directly modified. Whether individual properties are mutable or not is
920
+ * determined by the record instance itself.
921
+ *
922
+ * @public
923
+ * @class ReactiveDocument
924
+ */
925
+ class ReactiveDocument {
926
+ /**
927
+ * The links object for this document, if any
928
+ *
929
+ * e.g.
930
+ *
931
+ * ```
932
+ * {
933
+ * self: '/articles?page[number]=3',
934
+ * }
935
+ * ```
936
+ *
937
+ * @property links
938
+ * @type {object|undefined} - a links object
939
+ * @public
940
+ */
941
+
942
+ /**
943
+ * The primary data for this document, if any.
944
+ *
945
+ * If this document has no primary data (e.g. because it is an error document)
946
+ * this property will be `undefined`.
947
+ *
948
+ * For collections this will be an array of record instances,
949
+ * for single resource requests it will be a single record instance or null.
950
+ *
951
+ * @property data
952
+ * @public
953
+ * @type {object|Array<object>|null|undefined} - a data object
954
+ */
955
+
956
+ /**
957
+ * The errors returned by the API for this request, if any
958
+ *
959
+ * @property errors
960
+ * @public
961
+ * @type {object|undefined} - an errors object
962
+ */
963
+
964
+ /**
965
+ * The meta object for this document, if any
966
+ *
967
+ * @property meta
968
+ * @public
969
+ * @type {object|undefined} - a meta object
970
+ */
971
+
972
+ /**
973
+ * The identifier associated with this document, if any
974
+ *
975
+ * @property identifier
976
+ * @public
977
+ * @type {StableDocumentIdentifier|null}
978
+ */
979
+
980
+ constructor(store, identifier, localCache) {
981
+ this._store = store;
982
+ this._localCache = localCache;
983
+ this.identifier = identifier;
984
+
985
+ // TODO if we ever enable auto-cleanup of the cache, we will need to tear this down
986
+ // in a destroy method
987
+ if (identifier) {
988
+ store.notifications.subscribe(identifier, (_identifier, type) => {
989
+ switch (type) {
990
+ case 'updated':
991
+ // FIXME in the case of a collection we need to notify it's length
992
+ // and have it recalc
993
+ notifySignal(this, 'data');
994
+ notifySignal(this, 'links');
995
+ notifySignal(this, 'meta');
996
+ notifySignal(this, 'errors');
997
+ break;
998
+ }
999
+ });
1000
+ }
1001
+ }
1002
+ async #request(link, options) {
1003
+ const href = this.links?.[link];
1004
+ if (!href) {
1005
+ return null;
1006
+ }
1007
+ options.method = options.method || 'GET';
1008
+ Object.assign(options, {
1009
+ url: urlFromLink(href)
1010
+ });
1011
+ const response = await this._store.request(options);
1012
+ return response.content;
1013
+ }
1014
+
1015
+ /**
1016
+ * Fetches the related link for this document, returning a promise that resolves
1017
+ * with the document when the request completes. If no related link is present,
1018
+ * will fallback to the self link if present
1019
+ *
1020
+ * @method fetch
1021
+ * @public
1022
+ * @param {object} options
1023
+ * @return Promise<Document>
1024
+ */
1025
+ fetch(options = {}) {
1026
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1027
+ if (!test) {
1028
+ throw new Error(`No self or related link`);
1029
+ }
1030
+ })(this.links?.related || this.links?.self) : {};
1031
+ options.cacheOptions = options.cacheOptions || {};
1032
+ options.cacheOptions.key = this.identifier?.lid;
1033
+ return this.#request(this.links.related ? 'related' : 'self', options);
1034
+ }
1035
+
1036
+ /**
1037
+ * Fetches the next link for this document, returning a promise that resolves
1038
+ * with the new document when the request completes, or null if there is no
1039
+ * next link.
1040
+ *
1041
+ * @method next
1042
+ * @public
1043
+ * @param {object} options
1044
+ * @return Promise<Document | null>
1045
+ */
1046
+ next(options = {}) {
1047
+ return this.#request('next', options);
1048
+ }
1049
+
1050
+ /**
1051
+ * Fetches the prev link for this document, returning a promise that resolves
1052
+ * with the new document when the request completes, or null if there is no
1053
+ * prev link.
1054
+ *
1055
+ * @method prev
1056
+ * @public
1057
+ * @param {object} options
1058
+ * @return Promise<Document | null>
1059
+ */
1060
+ prev(options = {}) {
1061
+ return this.#request('prev', options);
1062
+ }
1063
+
1064
+ /**
1065
+ * Fetches the first link for this document, returning a promise that resolves
1066
+ * with the new document when the request completes, or null if there is no
1067
+ * first link.
1068
+ *
1069
+ * @method first
1070
+ * @public
1071
+ * @param {object} options
1072
+ * @return Promise<Document | null>
1073
+ */
1074
+ first(options = {}) {
1075
+ return this.#request('first', options);
1076
+ }
1077
+
1078
+ /**
1079
+ * Fetches the last link for this document, returning a promise that resolves
1080
+ * with the new document when the request completes, or null if there is no
1081
+ * last link.
1082
+ *
1083
+ * @method last
1084
+ * @public
1085
+ * @param {object} options
1086
+ * @return Promise<Document | null>
1087
+ */
1088
+ last(options = {}) {
1089
+ return this.#request('last', options);
1090
+ }
1091
+
1092
+ /**
1093
+ * Implemented for `JSON.stringify` support.
1094
+ *
1095
+ * Returns the JSON representation of the document wrapper.
1096
+ *
1097
+ * This is a shallow serialization, it does not deeply serialize
1098
+ * the document's contents, leaving that to the individual record
1099
+ * instances to determine how to do, if at all.
1100
+ *
1101
+ * @method toJSON
1102
+ * @public
1103
+ * @return
1104
+ */
1105
+ toJSON() {
1106
+ const data = {};
1107
+ data.identifier = this.identifier;
1108
+ if (this.data !== undefined) {
1109
+ data.data = this.data;
1110
+ }
1111
+ if (this.links !== undefined) {
1112
+ data.links = this.links;
1113
+ }
1114
+ if (this.errors !== undefined) {
1115
+ data.errors = this.errors;
1116
+ }
1117
+ if (this.meta !== undefined) {
1118
+ data.meta = this.meta;
1119
+ }
1120
+ return data;
1121
+ }
1122
+ }
1123
+ defineSubscription(ReactiveDocument.prototype, 'errors', {
1124
+ get() {
1125
+ const {
1126
+ identifier
1127
+ } = this;
1128
+ if (!identifier) {
1129
+ const {
1130
+ document
1131
+ } = this._localCache;
1132
+ if ('errors' in document) {
1133
+ return document.errors;
1134
+ }
1135
+ return;
1136
+ }
1137
+ const doc = this._store.cache.peek(identifier);
1138
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1139
+ if (!test) {
1140
+ throw new Error(`No cache data was found for the document '${identifier.lid}'`);
1141
+ }
1142
+ })(doc) : {};
1143
+ return 'errors' in doc ? doc.errors : undefined;
1144
+ }
1145
+ });
1146
+ defineSubscription(ReactiveDocument.prototype, 'data', {
1147
+ get() {
1148
+ const {
1149
+ identifier,
1150
+ _localCache
1151
+ } = this;
1152
+ const doc = identifier ? this._store.cache.peek(identifier) : _localCache.document;
1153
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1154
+ if (!test) {
1155
+ throw new Error(`No cache data was found for the document '${identifier?.lid ?? '<uncached document>'}'`);
1156
+ }
1157
+ })(doc) : {};
1158
+ const data = 'data' in doc ? doc.data : undefined;
1159
+ if (Array.isArray(data)) {
1160
+ return this._store.recordArrayManager.getCollection({
1161
+ type: identifier ? identifier.lid : _localCache.request.url,
1162
+ identifiers: data.slice(),
1163
+ doc: identifier ? undefined : doc,
1164
+ identifier: identifier ?? null
1165
+ });
1166
+ } else if (data) {
1167
+ return this._store.peekRecord(data);
1168
+ } else {
1169
+ return data;
1170
+ }
1171
+ }
1172
+ });
1173
+ defineSubscription(ReactiveDocument.prototype, 'links', {
1174
+ get() {
1175
+ const {
1176
+ identifier
1177
+ } = this;
1178
+ if (!identifier) {
1179
+ return this._localCache.document.links;
1180
+ }
1181
+ const data = this._store.cache.peek(identifier);
1182
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1183
+ if (!test) {
1184
+ throw new Error(`No cache data was found for the document '${identifier.lid}'`);
1185
+ }
1186
+ })(data) : {};
1187
+ return data.links;
1188
+ }
1189
+ });
1190
+ defineSubscription(ReactiveDocument.prototype, 'meta', {
1191
+ get() {
1192
+ const {
1193
+ identifier
1194
+ } = this;
1195
+ if (!identifier) {
1196
+ return this._localCache.document.meta;
1197
+ }
1198
+ const data = this._store.cache.peek(identifier);
1199
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
1200
+ if (!test) {
1201
+ throw new Error(`No cache data was found for the document '${identifier.lid}'`);
1202
+ }
1203
+ })(data) : {};
1204
+ return data.meta;
1205
+ }
1206
+ });
1207
+
905
1208
  /**
906
1209
  @module @ember-data/store
907
1210
  */
@@ -1282,12 +1585,13 @@ function storeFor(record) {
1282
1585
  return store;
1283
1586
  }
1284
1587
  class InstanceCache {
1285
- __instances = {
1286
- record: new Map(),
1287
- reference: new WeakMap()
1288
- };
1289
1588
  constructor(store) {
1290
1589
  this.store = store;
1590
+ this.__instances = {
1591
+ record: new Map(),
1592
+ reference: new WeakMap(),
1593
+ document: new Map()
1594
+ };
1291
1595
  this._storeWrapper = new CacheCapabilitiesManager(this.store);
1292
1596
  store.identifierCache.__configureMerge((identifier, matchedIdentifier, resourceData) => {
1293
1597
  let keptIdentifier = identifier;
@@ -1342,6 +1646,14 @@ class InstanceCache {
1342
1646
  peek(identifier) {
1343
1647
  return this.__instances.record.get(identifier);
1344
1648
  }
1649
+ getDocument(identifier) {
1650
+ let doc = this.__instances.document.get(identifier);
1651
+ if (!doc) {
1652
+ doc = new ReactiveDocument(this.store, identifier, null);
1653
+ this.__instances.document.set(identifier, doc);
1654
+ }
1655
+ return doc;
1656
+ }
1345
1657
  getRecord(identifier, properties) {
1346
1658
  let record = this.__instances.record.get(identifier);
1347
1659
  if (!record) {
@@ -2491,9 +2803,16 @@ class NotificationManager {
2491
2803
  }
2492
2804
  }
2493
2805
  }
2494
- } else if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
2495
- if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
2496
- count(`DISCARDED notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
2806
+ } else {
2807
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_NOTIFICATIONS)) {
2808
+ if (getGlobalConfig().WarpDrive.debug.LOG_NOTIFICATIONS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_NOTIFICATIONS) {
2809
+ log('notify', 'discarded', `${'type' in identifier ? identifier.type : 'document'}`, identifier.lid, `${value}`, key || '');
2810
+ }
2811
+ }
2812
+ if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_METRIC_COUNTS)) {
2813
+ if (getGlobalConfig().WarpDrive.debug.LOG_METRIC_COUNTS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_METRIC_COUNTS) {
2814
+ count(`DISCARDED notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
2815
+ }
2497
2816
  }
2498
2817
  }
2499
2818
  return hasSubscribers;
@@ -2671,6 +2990,7 @@ class IdentifierArray {
2671
2990
  isDestroying = false;
2672
2991
  isDestroyed = false;
2673
2992
  _updatingPromise = null;
2993
+ identifier;
2674
2994
  [IS_COLLECTION] = true;
2675
2995
  [SOURCE];
2676
2996
  [NOTIFY]() {
@@ -2709,6 +3029,7 @@ class IdentifierArray {
2709
3029
  this.modelName = options.type;
2710
3030
  this.store = options.store;
2711
3031
  this._manager = options.manager;
3032
+ this.identifier = options.identifier || null;
2712
3033
  this[SOURCE] = options.identifiers;
2713
3034
  this[ARRAY_SIGNAL] = createSignal(this, 'length');
2714
3035
  const store = options.store;
@@ -3165,6 +3486,12 @@ class RecordArrayManager {
3165
3486
  this._identifiers = new Map();
3166
3487
  this._set = new Map();
3167
3488
  this._visibilitySet = new Map();
3489
+ this._subscription = this.store.notifications.subscribe('document', (identifier, type) => {
3490
+ if (type === 'updated' && this._keyedArrays.has(identifier.lid)) {
3491
+ const array = this._keyedArrays.get(identifier.lid);
3492
+ this.dirtyArray(array, 0, true);
3493
+ }
3494
+ });
3168
3495
  this._subscription = this.store.notifications.subscribe('resource', (identifier, type) => {
3169
3496
  if (type === 'added') {
3170
3497
  this._visibilitySet.set(identifier, true);
@@ -3179,11 +3506,35 @@ class RecordArrayManager {
3179
3506
  }
3180
3507
  _syncArray(array) {
3181
3508
  const pending = this._pending.get(array);
3182
- if (!pending || this.isDestroying || this.isDestroyed) {
3509
+ const isRequestArray = isCollection(array);
3510
+ if (!isRequestArray && !pending || this.isDestroying || this.isDestroyed) {
3183
3511
  return;
3184
3512
  }
3185
- sync(array, pending, this._set.get(array));
3186
- this._pending.delete(array);
3513
+
3514
+ // first flush any staged changes
3515
+ if (pending) {
3516
+ sync(array, pending, this._set.get(array));
3517
+ this._pending.delete(array);
3518
+ }
3519
+
3520
+ // then pull new state if required
3521
+ if (isRequestArray) {
3522
+ const tag = array[ARRAY_SIGNAL];
3523
+ if (tag.reason === 'cache-sync') {
3524
+ tag.reason = null;
3525
+ const doc = this.store.cache.peek(array.identifier);
3526
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3527
+ if (!test) {
3528
+ throw new Error(`Expected to find a document for ${array.identifier.lid} but found none`);
3529
+ }
3530
+ })(doc) : {};
3531
+ const data = !('data' in doc) || !Array.isArray(doc.data) ? [] : doc.data;
3532
+ // TODO technically we should destroy here if
3533
+ // !('data' in doc) || !Array.isArray(doc.data)
3534
+ // is true.
3535
+ this.populateManagedArray(array, data, null);
3536
+ }
3537
+ }
3187
3538
  }
3188
3539
  mutate(mutation) {
3189
3540
  this.store.cache.mutate(mutation);
@@ -3222,9 +3573,13 @@ class RecordArrayManager {
3222
3573
  }
3223
3574
  return array;
3224
3575
  }
3225
- createArray(config) {
3576
+ getCollection(config) {
3577
+ if (config.identifier && this._keyedArrays.has(config.identifier.lid)) {
3578
+ return this._keyedArrays.get(config.identifier.lid);
3579
+ }
3226
3580
  const options = {
3227
3581
  type: config.type,
3582
+ identifier: config.identifier || null,
3228
3583
  links: config.doc?.links || null,
3229
3584
  meta: config.doc?.meta || null,
3230
3585
  query: config.query || null,
@@ -3237,16 +3592,22 @@ class RecordArrayManager {
3237
3592
  const array = new Collection(options);
3238
3593
  this._managed.add(array);
3239
3594
  this._set.set(array, new Set(options.identifiers || []));
3595
+ if (config.identifier) {
3596
+ this._keyedArrays.set(config.identifier.lid, array);
3597
+ }
3240
3598
  if (config.identifiers) {
3241
3599
  associate(this._identifiers, array, config.identifiers);
3242
3600
  }
3243
3601
  return array;
3244
3602
  }
3245
- dirtyArray(array, delta) {
3603
+ dirtyArray(array, delta, shouldSyncFromCache) {
3246
3604
  if (array === FAKE_ARR) {
3247
3605
  return;
3248
3606
  }
3249
3607
  const tag = array[ARRAY_SIGNAL];
3608
+ if (shouldSyncFromCache) {
3609
+ tag.reason = 'cache-sync';
3610
+ }
3250
3611
  if (!tag.shouldReset) {
3251
3612
  tag.shouldReset = true;
3252
3613
  addTransactionCB(array[NOTIFY]);
@@ -3305,13 +3666,18 @@ class RecordArrayManager {
3305
3666
  populateManagedArray(array, identifiers, payload) {
3306
3667
  this._pending.delete(array);
3307
3668
  const source = array[SOURCE];
3669
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3670
+ if (!test) {
3671
+ throw new Error(`The new state of the collection should not be using the same array reference as the original state.`);
3672
+ }
3673
+ })(source !== identifiers) : {};
3308
3674
  const old = source.slice();
3309
3675
  source.length = 0;
3310
3676
  fastPush(source, identifiers);
3311
3677
  this._set.set(array, new Set(identifiers));
3312
3678
  notifyArray(array);
3313
- array.meta = payload.meta || null;
3314
- array.links = payload.links || null;
3679
+ array.meta = payload?.meta || null;
3680
+ array.links = payload?.links || null;
3315
3681
  array.isLoaded = true;
3316
3682
  disassociate(this._identifiers, array, old);
3317
3683
  associate(this._identifiers, array, identifiers);
@@ -3325,7 +3691,7 @@ class RecordArrayManager {
3325
3691
  changes.delete(identifier);
3326
3692
  } else {
3327
3693
  changes.set(identifier, 'add');
3328
- this.dirtyArray(array, changes.size);
3694
+ this.dirtyArray(array, changes.size, false);
3329
3695
  }
3330
3696
  });
3331
3697
  }
@@ -3339,7 +3705,7 @@ class RecordArrayManager {
3339
3705
  changes.delete(identifier);
3340
3706
  } else {
3341
3707
  changes.set(identifier, 'del');
3342
- this.dirtyArray(array, changes.size);
3708
+ this.dirtyArray(array, changes.size, false);
3343
3709
  }
3344
3710
  });
3345
3711
  }
@@ -3444,6 +3810,9 @@ function sync(array, changes, arraySet) {
3444
3810
  */
3445
3811
  }
3446
3812
  }
3813
+ function isCollection(array) {
3814
+ return array.identifier !== null;
3815
+ }
3447
3816
 
3448
3817
  /**
3449
3818
  * @module @ember-data/store
@@ -3882,6 +4251,7 @@ const app = new EmberApp(defaults, {
3882
4251
  id: 'ember-data:deprecate-store-extends-ember-object',
3883
4252
  until: '6.0',
3884
4253
  for: 'ember-data',
4254
+ url: 'https://deprecations.emberjs.com/id/ember-data-deprecate-store-extends-ember-object',
3885
4255
  since: {
3886
4256
  available: '4.13',
3887
4257
  enabled: '5.4'
@@ -4029,7 +4399,6 @@ class Store extends BaseClass {
4029
4399
  // private
4030
4400
  this._requestCache = new RequestStateService(this);
4031
4401
  this._instanceCache = new InstanceCache(this);
4032
- this._documentCache = new Map();
4033
4402
  this.isDestroying = false;
4034
4403
  this.isDestroyed = false;
4035
4404
  }
@@ -5476,18 +5845,6 @@ class Store extends BaseClass {
5476
5845
  if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
5477
5846
  assertDestroyingStore(this, '_push');
5478
5847
  }
5479
- if (macroCondition(getGlobalConfig().WarpDrive.activeLogging.LOG_PAYLOADS)) {
5480
- if (getGlobalConfig().WarpDrive.debug.LOG_PAYLOADS || globalThis.getWarpDriveRuntimeConfig().debug.LOG_PAYLOADS) {
5481
- try {
5482
- const data = JSON.parse(JSON.stringify(jsonApiDoc));
5483
- // eslint-disable-next-line no-console
5484
- console.log('EmberData | Payload - push', data);
5485
- } catch {
5486
- // eslint-disable-next-line no-console
5487
- console.log('EmberData | Payload - push', jsonApiDoc);
5488
- }
5489
- }
5490
- }
5491
5848
  if (asyncFlush) {
5492
5849
  this._enableAsyncFlush = true;
5493
5850
  }
@@ -5748,212 +6105,6 @@ function extractIdentifierFromRecord$1(recordOrPromiseRecord) {
5748
6105
  const extract = recordIdentifierFor;
5749
6106
  return extract(recordOrPromiseRecord);
5750
6107
  }
5751
-
5752
- /**
5753
- * @module @ember-data/store
5754
- */
5755
- function urlFromLink(link) {
5756
- if (typeof link === 'string') return link;
5757
- return link.href;
5758
- }
5759
-
5760
- /**
5761
- * A Document is a class that wraps the response content from a request to the API
5762
- * returned by `Cache.put` or `Cache.peek`, converting resource-identifiers into
5763
- * record instances.
5764
- *
5765
- * It is not directly instantiated by the user, and its properties should not
5766
- * be directly modified. Whether individual properties are mutable or not is
5767
- * determined by the record instance itself.
5768
- *
5769
- * @public
5770
- * @class Document
5771
- */
5772
- class Document {
5773
- /**
5774
- * The links object for this document, if any
5775
- *
5776
- * e.g.
5777
- *
5778
- * ```
5779
- * {
5780
- * self: '/articles?page[number]=3',
5781
- * }
5782
- * ```
5783
- *
5784
- * @property links
5785
- * @type {object|undefined} - a links object
5786
- * @public
5787
- */
5788
-
5789
- /**
5790
- * The primary data for this document, if any.
5791
- *
5792
- * If this document has no primary data (e.g. because it is an error document)
5793
- * this property will be `undefined`.
5794
- *
5795
- * For collections this will be an array of record instances,
5796
- * for single resource requests it will be a single record instance or null.
5797
- *
5798
- * @property data
5799
- * @public
5800
- * @type {object|Array<object>|null|undefined} - a data object
5801
- */
5802
-
5803
- /**
5804
- * The errors returned by the API for this request, if any
5805
- *
5806
- * @property errors
5807
- * @public
5808
- * @type {object|undefined} - an errors object
5809
- */
5810
-
5811
- /**
5812
- * The meta object for this document, if any
5813
- *
5814
- * @property meta
5815
- * @public
5816
- * @type {object|undefined} - a meta object
5817
- */
5818
-
5819
- /**
5820
- * The identifier associated with this document, if any
5821
- *
5822
- * @property identifier
5823
- * @public
5824
- * @type {StableDocumentIdentifier|null}
5825
- */
5826
-
5827
- #store;
5828
- constructor(store, identifier) {
5829
- this.#store = store;
5830
- this.identifier = identifier;
5831
- }
5832
- async #request(link, options) {
5833
- const href = this.links?.[link];
5834
- if (!href) {
5835
- return null;
5836
- }
5837
- options.method = options.method || 'GET';
5838
- Object.assign(options, {
5839
- url: urlFromLink(href)
5840
- });
5841
- const response = await this.#store.request(options);
5842
- return response.content;
5843
- }
5844
-
5845
- /**
5846
- * Fetches the related link for this document, returning a promise that resolves
5847
- * with the document when the request completes. If no related link is present,
5848
- * will fallback to the self link if present
5849
- *
5850
- * @method fetch
5851
- * @public
5852
- * @param {object} options
5853
- * @return Promise<Document>
5854
- */
5855
- fetch(options = {}) {
5856
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
5857
- if (!test) {
5858
- throw new Error(`No self or related link`);
5859
- }
5860
- })(this.links?.related || this.links?.self) : {};
5861
- options.cacheOptions = options.cacheOptions || {};
5862
- options.cacheOptions.key = this.identifier?.lid;
5863
- return this.#request(this.links.related ? 'related' : 'self', options);
5864
- }
5865
-
5866
- /**
5867
- * Fetches the next link for this document, returning a promise that resolves
5868
- * with the new document when the request completes, or null if there is no
5869
- * next link.
5870
- *
5871
- * @method next
5872
- * @public
5873
- * @param {object} options
5874
- * @return Promise<Document | null>
5875
- */
5876
- next(options = {}) {
5877
- return this.#request('next', options);
5878
- }
5879
-
5880
- /**
5881
- * Fetches the prev link for this document, returning a promise that resolves
5882
- * with the new document when the request completes, or null if there is no
5883
- * prev link.
5884
- *
5885
- * @method prev
5886
- * @public
5887
- * @param {object} options
5888
- * @return Promise<Document | null>
5889
- */
5890
- prev(options = {}) {
5891
- return this.#request('prev', options);
5892
- }
5893
-
5894
- /**
5895
- * Fetches the first link for this document, returning a promise that resolves
5896
- * with the new document when the request completes, or null if there is no
5897
- * first link.
5898
- *
5899
- * @method first
5900
- * @public
5901
- * @param {object} options
5902
- * @return Promise<Document | null>
5903
- */
5904
- first(options = {}) {
5905
- return this.#request('first', options);
5906
- }
5907
-
5908
- /**
5909
- * Fetches the last link for this document, returning a promise that resolves
5910
- * with the new document when the request completes, or null if there is no
5911
- * last link.
5912
- *
5913
- * @method last
5914
- * @public
5915
- * @param {object} options
5916
- * @return Promise<Document | null>
5917
- */
5918
- last(options = {}) {
5919
- return this.#request('last', options);
5920
- }
5921
-
5922
- /**
5923
- * Implemented for `JSON.stringify` support.
5924
- *
5925
- * Returns the JSON representation of the document wrapper.
5926
- *
5927
- * This is a shallow serialization, it does not deeply serialize
5928
- * the document's contents, leaving that to the individual record
5929
- * instances to determine how to do, if at all.
5930
- *
5931
- * @method toJSON
5932
- * @public
5933
- * @return
5934
- */
5935
- toJSON() {
5936
- const data = {};
5937
- data.identifier = this.identifier;
5938
- if (this.data !== undefined) {
5939
- data.data = this.data;
5940
- }
5941
- if (this.links !== undefined) {
5942
- data.links = this.links;
5943
- }
5944
- if (this.errors !== undefined) {
5945
- data.errors = this.errors;
5946
- }
5947
- if (this.meta !== undefined) {
5948
- data.meta = this.meta;
5949
- }
5950
- return data;
5951
- }
5952
- }
5953
- defineSignal(Document.prototype, 'data');
5954
- defineSignal(Document.prototype, 'links');
5955
- defineSignal(Document.prototype, 'errors');
5956
- defineSignal(Document.prototype, 'meta');
5957
6108
  const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);
5958
6109
  function calcShouldFetch(store, request, hasCachedValue, identifier) {
5959
6110
  const {
@@ -5970,17 +6121,6 @@ function calcShouldBackgroundFetch(store, request, willFetch, identifier) {
5970
6121
  function isMutation(request) {
5971
6122
  return Boolean(request.op && MUTATION_OPS.has(request.op));
5972
6123
  }
5973
- function copyDocumentProperties(target, source) {
5974
- if ('links' in source) {
5975
- target.links = source.links;
5976
- }
5977
- if ('meta' in source) {
5978
- target.meta = source.meta;
5979
- }
5980
- if ('errors' in source) {
5981
- target.errors = source.errors;
5982
- }
5983
- }
5984
6124
  function isCacheAffecting(document) {
5985
6125
  if (!isMutation(document.request)) {
5986
6126
  return true;
@@ -6008,9 +6148,6 @@ function cloneError(error) {
6008
6148
  Object.assign(cloned, error);
6009
6149
  return cloned;
6010
6150
  }
6011
- function isErrorDocument(document) {
6012
- return 'errors' in document;
6013
- }
6014
6151
  function getPriority(identifier, deduped, priority) {
6015
6152
  if (identifier) {
6016
6153
  const existing = deduped.get(identifier);
@@ -6140,10 +6277,10 @@ const CacheHandler = {
6140
6277
  const shouldHydrate = context.request[EnableHydration] || false;
6141
6278
  context.setResponse(peeked.response);
6142
6279
  if ('error' in peeked) {
6143
- const content = shouldHydrate ? maybeUpdateErrorUiObjects(store, {
6280
+ const content = shouldHydrate ? maybeUpdateUiObjects(store, context.request, {
6144
6281
  shouldHydrate,
6145
6282
  identifier
6146
- }, peeked.content, true) : peeked.content;
6283
+ }, peeked.content) : peeked.content;
6147
6284
  const newError = cloneError(peeked);
6148
6285
  newError.content = content;
6149
6286
  throw newError;
@@ -6151,15 +6288,15 @@ const CacheHandler = {
6151
6288
  const result = shouldHydrate ? maybeUpdateUiObjects(store, context.request, {
6152
6289
  shouldHydrate,
6153
6290
  identifier
6154
- }, peeked.content, true) : peeked.content;
6291
+ }, peeked.content) : peeked.content;
6155
6292
  return result;
6156
6293
  }
6157
6294
  };
6158
- function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
6295
+ function maybeUpdateUiObjects(store, request, options, document) {
6159
6296
  const {
6160
6297
  identifier
6161
6298
  } = options;
6162
- if (!document) {
6299
+ if (!document || !options.shouldHydrate) {
6163
6300
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6164
6301
  if (!test) {
6165
6302
  throw new Error(`The CacheHandler expected response content but none was found`);
@@ -6167,97 +6304,16 @@ function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
6167
6304
  })(!options.shouldHydrate) : {};
6168
6305
  return document;
6169
6306
  }
6170
- if (Array.isArray(document.data)) {
6171
- const {
6172
- recordArrayManager
6173
- } = store;
6174
- if (!identifier) {
6175
- if (!options.shouldHydrate) {
6176
- return document;
6177
- }
6178
- const data = recordArrayManager.createArray({
6179
- type: request.url,
6180
- identifiers: document.data,
6181
- doc: document,
6182
- query: request
6183
- });
6184
- const doc = new Document(store, null);
6185
- doc.data = data;
6186
- doc.meta = document.meta;
6187
- doc.links = document.links;
6188
- return doc;
6189
- }
6190
- let managed = recordArrayManager._keyedArrays.get(identifier.lid);
6191
- if (!managed) {
6192
- managed = recordArrayManager.createArray({
6193
- type: identifier.lid,
6194
- identifiers: document.data,
6195
- doc: document
6196
- });
6197
- recordArrayManager._keyedArrays.set(identifier.lid, managed);
6198
- const doc = new Document(store, identifier);
6199
- doc.data = managed;
6200
- doc.meta = document.meta;
6201
- doc.links = document.links;
6202
- store._documentCache.set(identifier, doc);
6203
- return options.shouldHydrate ? doc : document;
6204
- } else {
6205
- const doc = store._documentCache.get(identifier);
6206
- if (!isFromCache) {
6207
- recordArrayManager.populateManagedArray(managed, document.data, document);
6208
- doc.data = managed;
6209
- doc.meta = document.meta;
6210
- doc.links = document.links;
6211
- }
6212
- return options.shouldHydrate ? doc : document;
6213
- }
6214
- } else {
6215
- if (!identifier && !options.shouldHydrate) {
6216
- return document;
6217
- }
6218
- const data = document.data ? store.peekRecord(document.data) : null;
6219
- let doc;
6220
- if (identifier) {
6221
- doc = store._documentCache.get(identifier);
6222
- }
6223
- if (!doc) {
6224
- doc = new Document(store, identifier);
6225
- doc.data = data;
6226
- copyDocumentProperties(doc, document);
6227
- if (identifier) {
6228
- store._documentCache.set(identifier, doc);
6229
- }
6230
- } else if (!isFromCache) {
6231
- doc.data = data;
6232
- copyDocumentProperties(doc, document);
6233
- }
6234
- return options.shouldHydrate ? doc : document;
6235
- }
6236
- }
6237
- function maybeUpdateErrorUiObjects(store, options, document, isFromCache) {
6238
- const {
6239
- identifier
6240
- } = options;
6241
-
6242
- // TODO investigate why ResourceErrorDocument is insufficient for expressing all error types
6243
- if (!isErrorDocument(document) || !identifier && !options.shouldHydrate) {
6244
- return document;
6245
- }
6246
- let doc;
6247
6307
  if (identifier) {
6248
- doc = store._documentCache.get(identifier);
6308
+ return store._instanceCache.getDocument(identifier);
6249
6309
  }
6250
- if (!doc) {
6251
- doc = new Document(store, identifier);
6252
- copyDocumentProperties(doc, document);
6253
- if (identifier) {
6254
- store._documentCache.set(identifier, doc);
6255
- }
6256
- } else if (!isFromCache) {
6257
- doc.data = undefined;
6258
- copyDocumentProperties(doc, document);
6259
- }
6260
- return options.shouldHydrate ? doc : document;
6310
+
6311
+ // if we don't have an identifier, we give the document
6312
+ // its own local cache
6313
+ return new ReactiveDocument(store, null, {
6314
+ request,
6315
+ document
6316
+ });
6261
6317
  }
6262
6318
  function updateCacheForSuccess(store, request, options, document) {
6263
6319
  let response = null;
@@ -6275,7 +6331,7 @@ function updateCacheForSuccess(store, request, options, document) {
6275
6331
  } else {
6276
6332
  response = store.cache.put(document);
6277
6333
  }
6278
- return maybeUpdateUiObjects(store, request, options, response, false);
6334
+ return maybeUpdateUiObjects(store, request, options, response);
6279
6335
  }
6280
6336
  function handleFetchSuccess(store, context, options, document) {
6281
6337
  const {
@@ -6308,7 +6364,7 @@ function updateCacheForError(store, context, options, error) {
6308
6364
  store.cache.commitWasRejected(record, errors);
6309
6365
  } else {
6310
6366
  response = store.cache.put(error);
6311
- return maybeUpdateErrorUiObjects(store, options, response, false);
6367
+ return maybeUpdateUiObjects(store, context.request, options, response);
6312
6368
  }
6313
6369
  }
6314
6370
  function handleFetchError(store, context, options, error) {
@@ -6813,7 +6869,7 @@ function assertNoDuplicates(collection, target, callback, reason) {
6813
6869
  }
6814
6870
  function mutateAddToRelatedRecords(collection, operationInfo, _SIGNAL) {
6815
6871
  mutate(collection, {
6816
- op: 'addToRelatedRecords',
6872
+ op: 'add',
6817
6873
  record: collection.identifier,
6818
6874
  field: collection.key,
6819
6875
  ...operationInfo
@@ -6821,7 +6877,7 @@ function mutateAddToRelatedRecords(collection, operationInfo, _SIGNAL) {
6821
6877
  }
6822
6878
  function mutateRemoveFromRelatedRecords(collection, operationInfo, _SIGNAL) {
6823
6879
  mutate(collection, {
6824
- op: 'removeFromRelatedRecords',
6880
+ op: 'remove',
6825
6881
  record: collection.identifier,
6826
6882
  field: collection.key,
6827
6883
  ...operationInfo
@@ -6860,4 +6916,4 @@ function mutate(collection, mutation, _SIGNAL) {
6860
6916
  collection._manager.mutate(mutation);
6861
6917
  addToTransaction(_SIGNAL);
6862
6918
  }
6863
- 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 };
6919
+ export { ARRAY_SIGNAL as A, CacheHandler as C, IdentifierArray as I, MUTATE as M, RecordArrayManager as R, Store as S, _clearCaches as _, setIdentifierGenerationMethod as a, setIdentifierUpdateMethod as b, setIdentifierForgetMethod as c, setIdentifierResetMethod as d, setKeyInfoForResource as e, isDocumentIdentifier as f, constructResource as g, coerceId as h, isStableIdentifier as i, ensureStringId as j, Collection as k, SOURCE as l, fastPush as m, notifyArray as n, removeRecordDataFor as o, peekCache as p, setRecordIdentifier as q, recordIdentifierFor as r, storeFor as s, StoreMap as t, setCacheFor as u, normalizeModelName as v, RelatedCollection as w, log as x, logGroup as y };