@ember-data/store 5.4.0-alpha.152 → 5.4.0-alpha.153

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/-private.js CHANGED
@@ -1 +1 @@
1
- export { A as ARRAY_SIGNAL, C as CacheHandler, j as CollectionRecordArray, I as LiveArray, M as MUTATE, R as RecordArrayManager, v as RelatedCollection, k as SOURCE, S as Store, q as StoreMap, _ as _clearCaches, u as _deprecatingNormalize, g as coerceId, f as constructResource, h as ensureStringId, l as fastPush, i as isStableIdentifier, w as log, x as logGroup, n as notifyArray, p as peekCache, r as recordIdentifierFor, m as removeRecordDataFor, t as setCacheFor, o as setRecordIdentifier, s as storeFor } from "./many-array-uP6jS6_J.js";
1
+ export { A as ARRAY_SIGNAL, C as CacheHandler, j as CollectionRecordArray, I as LiveArray, M as MUTATE, R as RecordArrayManager, v as RelatedCollection, k as SOURCE, S as Store, q as StoreMap, _ as _clearCaches, u as _deprecatingNormalize, g as coerceId, f as constructResource, h as ensureStringId, l as fastPush, i as isStableIdentifier, w as log, x as logGroup, n as notifyArray, p as peekCache, r as recordIdentifierFor, m as removeRecordDataFor, t as setCacheFor, o as setRecordIdentifier, s as storeFor } from "./many-array-BBvney_-.js";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { C as CacheHandler, S as default, r as recordIdentifierFor, c as setIdentifierForgetMethod, a as setIdentifierGenerationMethod, d as setIdentifierResetMethod, b as setIdentifierUpdateMethod, e as setKeyInfoForResource, s as storeFor } from "./many-array-uP6jS6_J.js";
1
+ export { C as CacheHandler, S as default, r as recordIdentifierFor, c as setIdentifierForgetMethod, a as setIdentifierGenerationMethod, d as setIdentifierResetMethod, b as setIdentifierUpdateMethod, e as setKeyInfoForResource, s as storeFor } from "./many-array-BBvney_-.js";
2
2
  import '@ember/debug';
3
3
  import '@embroider/macros';
4
4
  import '@ember-data/request-utils/string';
@@ -4,7 +4,7 @@ import { EnableHydration, SkipCache } from '@warp-drive/core-types/request';
4
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 { defineSignal, createSignal, subscribe, createArrayTags, addToTransaction, addTransactionCB, defineSubscription, notifySignal } 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';
@@ -2678,6 +2678,7 @@ class IdentifierArray {
2678
2678
  isDestroying = false;
2679
2679
  isDestroyed = false;
2680
2680
  _updatingPromise = null;
2681
+ identifier;
2681
2682
  [IS_COLLECTION] = true;
2682
2683
  [SOURCE];
2683
2684
  [NOTIFY]() {
@@ -2716,6 +2717,7 @@ class IdentifierArray {
2716
2717
  this.modelName = options.type;
2717
2718
  this.store = options.store;
2718
2719
  this._manager = options.manager;
2720
+ this.identifier = options.identifier || null;
2719
2721
  this[SOURCE] = options.identifiers;
2720
2722
  this[ARRAY_SIGNAL] = createSignal(this, 'length');
2721
2723
  const store = options.store;
@@ -3172,6 +3174,12 @@ class RecordArrayManager {
3172
3174
  this._identifiers = new Map();
3173
3175
  this._set = new Map();
3174
3176
  this._visibilitySet = new Map();
3177
+ this._subscription = this.store.notifications.subscribe('document', (identifier, type) => {
3178
+ if (type === 'updated' && this._keyedArrays.has(identifier.lid)) {
3179
+ const array = this._keyedArrays.get(identifier.lid);
3180
+ this.dirtyArray(array, 0, true);
3181
+ }
3182
+ });
3175
3183
  this._subscription = this.store.notifications.subscribe('resource', (identifier, type) => {
3176
3184
  if (type === 'added') {
3177
3185
  this._visibilitySet.set(identifier, true);
@@ -3186,11 +3194,35 @@ class RecordArrayManager {
3186
3194
  }
3187
3195
  _syncArray(array) {
3188
3196
  const pending = this._pending.get(array);
3189
- if (!pending || this.isDestroying || this.isDestroyed) {
3197
+ const isRequestArray = isCollection(array);
3198
+ if (!isRequestArray && !pending || this.isDestroying || this.isDestroyed) {
3190
3199
  return;
3191
3200
  }
3192
- sync(array, pending, this._set.get(array));
3193
- this._pending.delete(array);
3201
+
3202
+ // first flush any staged changes
3203
+ if (pending) {
3204
+ sync(array, pending, this._set.get(array));
3205
+ this._pending.delete(array);
3206
+ }
3207
+
3208
+ // then pull new state if required
3209
+ if (isRequestArray) {
3210
+ const tag = array[ARRAY_SIGNAL];
3211
+ if (tag.reason === 'cache-sync') {
3212
+ tag.reason = null;
3213
+ const doc = this.store.cache.peek(array.identifier);
3214
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
3215
+ if (!test) {
3216
+ throw new Error(`Expected to find a document for ${array.identifier.lid} but found none`);
3217
+ }
3218
+ })(doc) : {};
3219
+ const data = !('data' in doc) || !Array.isArray(doc.data) ? [] : doc.data;
3220
+ // TODO technically we should destroy here if
3221
+ // !('data' in doc) || !Array.isArray(doc.data)
3222
+ // is true.
3223
+ this.populateManagedArray(array, data, null);
3224
+ }
3225
+ }
3194
3226
  }
3195
3227
  mutate(mutation) {
3196
3228
  this.store.cache.mutate(mutation);
@@ -3229,9 +3261,13 @@ class RecordArrayManager {
3229
3261
  }
3230
3262
  return array;
3231
3263
  }
3232
- createArray(config) {
3264
+ getCollection(config) {
3265
+ if (config.identifier && this._keyedArrays.has(config.identifier.lid)) {
3266
+ return this._keyedArrays.get(config.identifier.lid);
3267
+ }
3233
3268
  const options = {
3234
3269
  type: config.type,
3270
+ identifier: config.identifier || null,
3235
3271
  links: config.doc?.links || null,
3236
3272
  meta: config.doc?.meta || null,
3237
3273
  query: config.query || null,
@@ -3244,16 +3280,22 @@ class RecordArrayManager {
3244
3280
  const array = new Collection(options);
3245
3281
  this._managed.add(array);
3246
3282
  this._set.set(array, new Set(options.identifiers || []));
3283
+ if (config.identifier) {
3284
+ this._keyedArrays.set(config.identifier.lid, array);
3285
+ }
3247
3286
  if (config.identifiers) {
3248
3287
  associate(this._identifiers, array, config.identifiers);
3249
3288
  }
3250
3289
  return array;
3251
3290
  }
3252
- dirtyArray(array, delta) {
3291
+ dirtyArray(array, delta, shouldSyncFromCache) {
3253
3292
  if (array === FAKE_ARR) {
3254
3293
  return;
3255
3294
  }
3256
3295
  const tag = array[ARRAY_SIGNAL];
3296
+ if (shouldSyncFromCache) {
3297
+ tag.reason = 'cache-sync';
3298
+ }
3257
3299
  if (!tag.shouldReset) {
3258
3300
  tag.shouldReset = true;
3259
3301
  addTransactionCB(array[NOTIFY]);
@@ -3317,8 +3359,8 @@ class RecordArrayManager {
3317
3359
  fastPush(source, identifiers);
3318
3360
  this._set.set(array, new Set(identifiers));
3319
3361
  notifyArray(array);
3320
- array.meta = payload.meta || null;
3321
- array.links = payload.links || null;
3362
+ array.meta = payload?.meta || null;
3363
+ array.links = payload?.links || null;
3322
3364
  array.isLoaded = true;
3323
3365
  disassociate(this._identifiers, array, old);
3324
3366
  associate(this._identifiers, array, identifiers);
@@ -3332,7 +3374,7 @@ class RecordArrayManager {
3332
3374
  changes.delete(identifier);
3333
3375
  } else {
3334
3376
  changes.set(identifier, 'add');
3335
- this.dirtyArray(array, changes.size);
3377
+ this.dirtyArray(array, changes.size, false);
3336
3378
  }
3337
3379
  });
3338
3380
  }
@@ -3346,7 +3388,7 @@ class RecordArrayManager {
3346
3388
  changes.delete(identifier);
3347
3389
  } else {
3348
3390
  changes.set(identifier, 'del');
3349
- this.dirtyArray(array, changes.size);
3391
+ this.dirtyArray(array, changes.size, false);
3350
3392
  }
3351
3393
  });
3352
3394
  }
@@ -3451,6 +3493,9 @@ function sync(array, changes, arraySet) {
3451
3493
  */
3452
3494
  }
3453
3495
  }
3496
+ function isCollection(array) {
3497
+ return array.identifier !== null;
3498
+ }
3454
3499
 
3455
3500
  /**
3456
3501
  * @module @ember-data/store
@@ -5774,9 +5819,9 @@ function urlFromLink(link) {
5774
5819
  * determined by the record instance itself.
5775
5820
  *
5776
5821
  * @public
5777
- * @class Document
5822
+ * @class ReactiveDocument
5778
5823
  */
5779
- class Document {
5824
+ class ReactiveDocument {
5780
5825
  /**
5781
5826
  * The links object for this document, if any
5782
5827
  *
@@ -5831,10 +5876,27 @@ class Document {
5831
5876
  * @type {StableDocumentIdentifier|null}
5832
5877
  */
5833
5878
 
5834
- #store;
5835
- constructor(store, identifier) {
5836
- this.#store = store;
5879
+ constructor(store, identifier, localCache) {
5880
+ this._store = store;
5881
+ this._localCache = localCache;
5837
5882
  this.identifier = identifier;
5883
+
5884
+ // TODO if we ever enable auto-cleanup of the cache, we will need to tear this down
5885
+ // in a destroy method
5886
+ if (identifier) {
5887
+ store.notifications.subscribe(identifier, (_identifier, type) => {
5888
+ switch (type) {
5889
+ case 'updated':
5890
+ // FIXME in the case of a collection we need to notify it's length
5891
+ // and have it recalc
5892
+ notifySignal(this, 'data');
5893
+ notifySignal(this, 'links');
5894
+ notifySignal(this, 'meta');
5895
+ notifySignal(this, 'errors');
5896
+ break;
5897
+ }
5898
+ });
5899
+ }
5838
5900
  }
5839
5901
  async #request(link, options) {
5840
5902
  const href = this.links?.[link];
@@ -5845,7 +5907,7 @@ class Document {
5845
5907
  Object.assign(options, {
5846
5908
  url: urlFromLink(href)
5847
5909
  });
5848
- const response = await this.#store.request(options);
5910
+ const response = await this._store.request(options);
5849
5911
  return response.content;
5850
5912
  }
5851
5913
 
@@ -5957,10 +6019,90 @@ class Document {
5957
6019
  return data;
5958
6020
  }
5959
6021
  }
5960
- defineSignal(Document.prototype, 'data');
5961
- defineSignal(Document.prototype, 'links');
5962
- defineSignal(Document.prototype, 'errors');
5963
- defineSignal(Document.prototype, 'meta');
6022
+ defineSubscription(ReactiveDocument.prototype, 'errors', {
6023
+ get() {
6024
+ const {
6025
+ identifier
6026
+ } = this;
6027
+ if (!identifier) {
6028
+ const {
6029
+ document
6030
+ } = this._localCache;
6031
+ if ('errors' in document) {
6032
+ return document.errors;
6033
+ }
6034
+ return;
6035
+ }
6036
+ const doc = this._store.cache.peek(identifier);
6037
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6038
+ if (!test) {
6039
+ throw new Error(`No cache data was found for the document '${identifier.lid}'`);
6040
+ }
6041
+ })(doc) : {};
6042
+ return 'errors' in doc ? doc.errors : undefined;
6043
+ }
6044
+ });
6045
+ defineSubscription(ReactiveDocument.prototype, 'data', {
6046
+ get() {
6047
+ const {
6048
+ identifier,
6049
+ _localCache
6050
+ } = this;
6051
+ const doc = identifier ? this._store.cache.peek(identifier) : _localCache.document;
6052
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6053
+ if (!test) {
6054
+ throw new Error(`No cache data was found for the document '${identifier?.lid ?? '<uncached document>'}'`);
6055
+ }
6056
+ })(doc) : {};
6057
+ const data = 'data' in doc ? doc.data : undefined;
6058
+ if (Array.isArray(data)) {
6059
+ return this._store.recordArrayManager.getCollection({
6060
+ type: identifier ? identifier.lid : _localCache.request.url,
6061
+ identifiers: data,
6062
+ doc: identifier ? undefined : doc,
6063
+ identifier: identifier ?? null
6064
+ });
6065
+ } else if (data) {
6066
+ return this._store.peekRecord(data);
6067
+ } else {
6068
+ return data;
6069
+ }
6070
+ }
6071
+ });
6072
+ defineSubscription(ReactiveDocument.prototype, 'links', {
6073
+ get() {
6074
+ const {
6075
+ identifier
6076
+ } = this;
6077
+ if (!identifier) {
6078
+ return this._localCache.document.links;
6079
+ }
6080
+ const data = this._store.cache.peek(identifier);
6081
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6082
+ if (!test) {
6083
+ throw new Error(`No cache data was found for the document '${identifier.lid}'`);
6084
+ }
6085
+ })(data) : {};
6086
+ return data.links;
6087
+ }
6088
+ });
6089
+ defineSubscription(ReactiveDocument.prototype, 'meta', {
6090
+ get() {
6091
+ const {
6092
+ identifier
6093
+ } = this;
6094
+ if (!identifier) {
6095
+ return this._localCache.document.meta;
6096
+ }
6097
+ const data = this._store.cache.peek(identifier);
6098
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6099
+ if (!test) {
6100
+ throw new Error(`No cache data was found for the document '${identifier.lid}'`);
6101
+ }
6102
+ })(data) : {};
6103
+ return data.meta;
6104
+ }
6105
+ });
5964
6106
  const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);
5965
6107
  function calcShouldFetch(store, request, hasCachedValue, identifier) {
5966
6108
  const {
@@ -5977,17 +6119,6 @@ function calcShouldBackgroundFetch(store, request, willFetch, identifier) {
5977
6119
  function isMutation(request) {
5978
6120
  return Boolean(request.op && MUTATION_OPS.has(request.op));
5979
6121
  }
5980
- function copyDocumentProperties(target, source) {
5981
- if ('links' in source) {
5982
- target.links = source.links;
5983
- }
5984
- if ('meta' in source) {
5985
- target.meta = source.meta;
5986
- }
5987
- if ('errors' in source) {
5988
- target.errors = source.errors;
5989
- }
5990
- }
5991
6122
  function isCacheAffecting(document) {
5992
6123
  if (!isMutation(document.request)) {
5993
6124
  return true;
@@ -6015,9 +6146,6 @@ function cloneError(error) {
6015
6146
  Object.assign(cloned, error);
6016
6147
  return cloned;
6017
6148
  }
6018
- function isErrorDocument(document) {
6019
- return 'errors' in document;
6020
- }
6021
6149
  function getPriority(identifier, deduped, priority) {
6022
6150
  if (identifier) {
6023
6151
  const existing = deduped.get(identifier);
@@ -6147,10 +6275,10 @@ const CacheHandler = {
6147
6275
  const shouldHydrate = context.request[EnableHydration] || false;
6148
6276
  context.setResponse(peeked.response);
6149
6277
  if ('error' in peeked) {
6150
- const content = shouldHydrate ? maybeUpdateErrorUiObjects(store, {
6278
+ const content = shouldHydrate ? maybeUpdateUiObjects(store, context.request, {
6151
6279
  shouldHydrate,
6152
6280
  identifier
6153
- }, peeked.content, true) : peeked.content;
6281
+ }, peeked.content) : peeked.content;
6154
6282
  const newError = cloneError(peeked);
6155
6283
  newError.content = content;
6156
6284
  throw newError;
@@ -6158,15 +6286,15 @@ const CacheHandler = {
6158
6286
  const result = shouldHydrate ? maybeUpdateUiObjects(store, context.request, {
6159
6287
  shouldHydrate,
6160
6288
  identifier
6161
- }, peeked.content, true) : peeked.content;
6289
+ }, peeked.content) : peeked.content;
6162
6290
  return result;
6163
6291
  }
6164
6292
  };
6165
- function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
6293
+ function maybeUpdateUiObjects(store, request, options, document) {
6166
6294
  const {
6167
6295
  identifier
6168
6296
  } = options;
6169
- if (!document) {
6297
+ if (!document || !options.shouldHydrate) {
6170
6298
  macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
6171
6299
  if (!test) {
6172
6300
  throw new Error(`The CacheHandler expected response content but none was found`);
@@ -6174,97 +6302,21 @@ function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
6174
6302
  })(!options.shouldHydrate) : {};
6175
6303
  return document;
6176
6304
  }
6177
- if (Array.isArray(document.data)) {
6178
- const {
6179
- recordArrayManager
6180
- } = store;
6181
- if (!identifier) {
6182
- if (!options.shouldHydrate) {
6183
- return document;
6184
- }
6185
- const data = recordArrayManager.createArray({
6186
- type: request.url,
6187
- identifiers: document.data,
6188
- doc: document,
6189
- query: request
6190
- });
6191
- const doc = new Document(store, null);
6192
- doc.data = data;
6193
- doc.meta = document.meta;
6194
- doc.links = document.links;
6195
- return doc;
6196
- }
6197
- let managed = recordArrayManager._keyedArrays.get(identifier.lid);
6198
- if (!managed) {
6199
- managed = recordArrayManager.createArray({
6200
- type: identifier.lid,
6201
- identifiers: document.data,
6202
- doc: document
6203
- });
6204
- recordArrayManager._keyedArrays.set(identifier.lid, managed);
6205
- const doc = new Document(store, identifier);
6206
- doc.data = managed;
6207
- doc.meta = document.meta;
6208
- doc.links = document.links;
6209
- store._documentCache.set(identifier, doc);
6210
- return options.shouldHydrate ? doc : document;
6211
- } else {
6212
- const doc = store._documentCache.get(identifier);
6213
- if (!isFromCache) {
6214
- recordArrayManager.populateManagedArray(managed, document.data, document);
6215
- doc.data = managed;
6216
- doc.meta = document.meta;
6217
- doc.links = document.links;
6218
- }
6219
- return options.shouldHydrate ? doc : document;
6220
- }
6221
- } else {
6222
- if (!identifier && !options.shouldHydrate) {
6223
- return document;
6224
- }
6225
- const data = document.data ? store.peekRecord(document.data) : null;
6226
- let doc;
6227
- if (identifier) {
6228
- doc = store._documentCache.get(identifier);
6229
- }
6230
- if (!doc) {
6231
- doc = new Document(store, identifier);
6232
- doc.data = data;
6233
- copyDocumentProperties(doc, document);
6234
- if (identifier) {
6235
- store._documentCache.set(identifier, doc);
6236
- }
6237
- } else if (!isFromCache) {
6238
- doc.data = data;
6239
- copyDocumentProperties(doc, document);
6240
- }
6241
- return options.shouldHydrate ? doc : document;
6242
- }
6243
- }
6244
- function maybeUpdateErrorUiObjects(store, options, document, isFromCache) {
6245
- const {
6246
- identifier
6247
- } = options;
6248
-
6249
- // TODO investigate why ResourceErrorDocument is insufficient for expressing all error types
6250
- if (!isErrorDocument(document) || !identifier && !options.shouldHydrate) {
6251
- return document;
6252
- }
6253
- let doc;
6254
6305
  if (identifier) {
6255
- doc = store._documentCache.get(identifier);
6256
- }
6257
- if (!doc) {
6258
- doc = new Document(store, identifier);
6259
- copyDocumentProperties(doc, document);
6260
- if (identifier) {
6306
+ let doc = store._documentCache.get(identifier);
6307
+ if (!doc) {
6308
+ doc = new ReactiveDocument(store, identifier, null);
6261
6309
  store._documentCache.set(identifier, doc);
6262
6310
  }
6263
- } else if (!isFromCache) {
6264
- doc.data = undefined;
6265
- copyDocumentProperties(doc, document);
6311
+ return doc;
6266
6312
  }
6267
- return options.shouldHydrate ? doc : document;
6313
+
6314
+ // if we don't have an identifier, we give the document
6315
+ // its own local cache
6316
+ return new ReactiveDocument(store, null, {
6317
+ request,
6318
+ document
6319
+ });
6268
6320
  }
6269
6321
  function updateCacheForSuccess(store, request, options, document) {
6270
6322
  let response = null;
@@ -6282,7 +6334,7 @@ function updateCacheForSuccess(store, request, options, document) {
6282
6334
  } else {
6283
6335
  response = store.cache.put(document);
6284
6336
  }
6285
- return maybeUpdateUiObjects(store, request, options, response, false);
6337
+ return maybeUpdateUiObjects(store, request, options, response);
6286
6338
  }
6287
6339
  function handleFetchSuccess(store, context, options, document) {
6288
6340
  const {
@@ -6315,7 +6367,7 @@ function updateCacheForError(store, context, options, error) {
6315
6367
  store.cache.commitWasRejected(record, errors);
6316
6368
  } else {
6317
6369
  response = store.cache.put(error);
6318
- return maybeUpdateErrorUiObjects(store, options, response, false);
6370
+ return maybeUpdateUiObjects(store, context.request, options, response);
6319
6371
  }
6320
6372
  }
6321
6373
  function handleFetchError(store, context, options, error) {