@ember-data/store 5.4.0-alpha.9 → 5.4.0-beta.1

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/addon/-private.js CHANGED
@@ -1 +1 @@
1
- export { f as AdapterPopulatedRecordArray, C as CacheHandler, h as IDENTIFIER_ARRAY_TAG, I as IdentifierArray, M as MUTATE, I as RecordArray, R as RecordArrayManager, g as SOURCE, S as Store, m as StoreMap, _ as _clearCaches, e as coerceId, j as fastPush, i as isStableIdentifier, n as notifyArray, p as peekCache, r as recordIdentifierFor, k as removeRecordDataFor, o as setCacheFor, c as setIdentifierForgetMethod, a as setIdentifierGenerationMethod, d as setIdentifierResetMethod, b as setIdentifierUpdateMethod, l as setRecordIdentifier, s as storeFor } from "./store-service-fc1e0bd5";
1
+ export { f as AdapterPopulatedRecordArray, C as CacheHandler, h as IDENTIFIER_ARRAY_TAG, I as IdentifierArray, M as MUTATE, I as RecordArray, R as RecordArrayManager, g as SOURCE, S as Store, m as StoreMap, _ as _clearCaches, e as coerceId, j as fastPush, i as isStableIdentifier, n as notifyArray, p as peekCache, r as recordIdentifierFor, k as removeRecordDataFor, o as setCacheFor, c as setIdentifierForgetMethod, a as setIdentifierGenerationMethod, d as setIdentifierResetMethod, b as setIdentifierUpdateMethod, l as setRecordIdentifier, s as storeFor } from "./store-service-f6cb9898";
package/addon/index.js CHANGED
@@ -1 +1 @@
1
- export { C as CacheHandler, S as default, r as recordIdentifierFor, c as setIdentifierForgetMethod, a as setIdentifierGenerationMethod, d as setIdentifierResetMethod, b as setIdentifierUpdateMethod, s as storeFor } from "./store-service-fc1e0bd5";
1
+ export { C as CacheHandler, S as default, r as recordIdentifierFor, c as setIdentifierForgetMethod, a as setIdentifierGenerationMethod, d as setIdentifierResetMethod, b as setIdentifierUpdateMethod, s as storeFor } from "./store-service-f6cb9898";
@@ -2,9 +2,9 @@ import { macroCondition, getOwnConfig } from '@embroider/macros';
2
2
  import { getOwner } from '@ember/application';
3
3
  import { assert, deprecate, warn } from '@ember/debug';
4
4
  import EmberObject from '@ember/object';
5
- import { _backburner } from '@ember/runloop';
6
5
  import { tracked } from '@glimmer/tracking';
7
6
  import { dasherize } from '@ember/string';
7
+ import { _backburner } from '@ember/runloop';
8
8
  import { addToTransaction, subscribe, addTransactionCB } from '@ember-data/tracking/-private';
9
9
  import { tagForProperty } from '@ember/-internals/metal';
10
10
  import { dependentKeyCompat } from '@ember/object/compat';
@@ -233,11 +233,12 @@ function maybeUpdateUiObjects(store, request, options, document, isFromCache) {
233
233
  return options.shouldHydrate ? doc : document;
234
234
  }
235
235
  }
236
+ const MUTATION_OPS = new Set(['createRecord', 'updateRecord', 'deleteRecord']);
236
237
  function calcShouldFetch(store, request, hasCachedValue, identifier) {
237
238
  const {
238
239
  cacheOptions
239
240
  } = request;
240
- return cacheOptions?.reload || !hasCachedValue || (store.lifetimes && identifier ? store.lifetimes.isHardExpired(identifier) : false);
241
+ return request.op && MUTATION_OPS.has(request.op) || cacheOptions?.reload || !hasCachedValue || (store.lifetimes && identifier ? store.lifetimes.isHardExpired(identifier) : false);
241
242
  }
242
243
  function calcShouldBackgroundFetch(store, request, willFetch, identifier) {
243
244
  const {
@@ -245,17 +246,31 @@ function calcShouldBackgroundFetch(store, request, willFetch, identifier) {
245
246
  } = request;
246
247
  return !willFetch && (cacheOptions?.backgroundReload || (store.lifetimes && identifier ? store.lifetimes.isSoftExpired(identifier) : false));
247
248
  }
249
+ function isMutation(request) {
250
+ return Boolean(request.op && MUTATION_OPS.has(request.op));
251
+ }
248
252
  function fetchContentAndHydrate(next, context, identifier, shouldFetch, shouldBackgroundFetch) {
249
253
  const {
250
254
  store
251
255
  } = context.request;
252
256
  const shouldHydrate = context.request[Symbol.for('ember-data:enable-hydration')] || false;
253
- return next(context.request).then(document => {
257
+ let isMut = false;
258
+ if (isMutation(context.request)) {
259
+ isMut = true;
260
+ const record = context.request.data?.record;
261
+ assert(`Expected to receive a list of records included in the ${context.request.op} request`, record);
262
+ store.cache.willCommit(record, context);
263
+ }
264
+ const promise = next(context.request).then(document => {
254
265
  store.requestManager._pending.delete(context.id);
255
266
  store._enableAsyncFlush = true;
256
267
  let response;
257
268
  store._join(() => {
258
- response = store.cache.put(document);
269
+ if (isMutation(context.request)) {
270
+ response = store.cache.didCommit(context.request.data.record, document);
271
+ } else {
272
+ response = store.cache.put(document);
273
+ }
259
274
  response = maybeUpdateUiObjects(store, context.request, {
260
275
  shouldHydrate,
261
276
  shouldFetch,
@@ -278,13 +293,22 @@ function fetchContentAndHydrate(next, context, identifier, shouldFetch, shouldBa
278
293
  store._enableAsyncFlush = true;
279
294
  let response;
280
295
  store._join(() => {
281
- response = store.cache.put(error);
282
- response = maybeUpdateUiObjects(store, context.request, {
283
- shouldHydrate,
284
- shouldFetch,
285
- shouldBackgroundFetch,
286
- identifier
287
- }, response, false);
296
+ if (isMutation(context.request)) {
297
+ // TODO similar to didCommit we should spec this to be similar to cache.put for handling full response
298
+ // currently we let the response remain undefiend.
299
+ const errors = error && error.content && typeof error.content === 'object' && 'errors' in error.content && Array.isArray(error.content.errors) ? error.content.errors : undefined;
300
+ store.cache.commitWasRejected(context.request.data.record, errors);
301
+ // re-throw the original error to preserve `errors` property.
302
+ throw error;
303
+ } else {
304
+ response = store.cache.put(error);
305
+ response = maybeUpdateUiObjects(store, context.request, {
306
+ shouldHydrate,
307
+ shouldFetch,
308
+ shouldBackgroundFetch,
309
+ identifier
310
+ }, response, false);
311
+ }
288
312
  });
289
313
  store._enableAsyncFlush = null;
290
314
  if (!shouldBackgroundFetch) {
@@ -295,6 +319,19 @@ function fetchContentAndHydrate(next, context, identifier, shouldFetch, shouldBa
295
319
  store.notifications._flush();
296
320
  }
297
321
  });
322
+ if (!isMut) {
323
+ return promise;
324
+ }
325
+ assert(`Expected a mutation`, isMutation(context.request));
326
+
327
+ // for mutations we need to enqueue the promise with the requestStateService
328
+ return store._requestCache._enqueue(promise, {
329
+ data: [{
330
+ op: 'saveRecord',
331
+ recordIdentifier: context.request.data.record,
332
+ options: undefined
333
+ }]
334
+ });
298
335
  }
299
336
  function cloneError(error) {
300
337
  const cloned = new Error(error.message);
@@ -2588,8 +2625,10 @@ const IS_COLLECTION = Symbol.for('Collection');
2588
2625
  function notifyArray(arr) {
2589
2626
  addToTransaction(arr[IDENTIFIER_ARRAY_TAG]);
2590
2627
  if (macroCondition(getOwnConfig().deprecations.DEPRECATE_COMPUTED_CHAINS)) {
2628
+ // @ts-expect-error tagForProperty is mistyped to Tag instead of DirtyableTag
2591
2629
  // eslint-disable-next-line
2592
2630
  dirtyTag(tagForProperty(arr, 'length'));
2631
+ // @ts-expect-error tagForProperty is mistyped to Tag instead of DirtyableTag
2593
2632
  // eslint-disable-next-line
2594
2633
  dirtyTag(tagForProperty(arr, '[]'));
2595
2634
  }
@@ -2879,7 +2918,7 @@ let IdentifierArray = (_class3 = class IdentifierArray {
2879
2918
  });
2880
2919
  if (macroCondition(getOwnConfig().env.DEBUG)) {
2881
2920
  const meta = Ember.meta(this);
2882
- meta.hasMixin = mixin => {
2921
+ meta.addMixin = mixin => {
2883
2922
  assert(`Do not call A() on EmberData RecordArrays`);
2884
2923
  };
2885
2924
  }
@@ -4108,43 +4147,41 @@ class Store extends EmberObject {
4108
4147
  //
4109
4148
  // to remove this, we would need to move to a new `async` API.
4110
4149
  let record;
4111
- _backburner.join(() => {
4112
- this._join(() => {
4113
- let normalizedModelName = normalizeModelName(modelName);
4114
- let properties = {
4115
- ...inputProperties
4116
- };
4150
+ this._join(() => {
4151
+ let normalizedModelName = normalizeModelName(modelName);
4152
+ let properties = {
4153
+ ...inputProperties
4154
+ };
4117
4155
 
4118
- // If the passed properties do not include a primary key,
4119
- // give the adapter an opportunity to generate one. Typically,
4120
- // client-side ID generators will use something like uuid.js
4121
- // to avoid conflicts.
4156
+ // If the passed properties do not include a primary key,
4157
+ // give the adapter an opportunity to generate one. Typically,
4158
+ // client-side ID generators will use something like uuid.js
4159
+ // to avoid conflicts.
4122
4160
 
4123
- if (properties.id === null || properties.id === undefined) {
4124
- let adapter = this.adapterFor(modelName, true);
4125
- if (adapter && adapter.generateIdForRecord) {
4126
- properties.id = adapter.generateIdForRecord(this, modelName, properties);
4127
- } else {
4128
- properties.id = null;
4129
- }
4161
+ if (properties.id === null || properties.id === undefined) {
4162
+ let adapter = this.adapterFor(modelName, true);
4163
+ if (adapter && adapter.generateIdForRecord) {
4164
+ properties.id = adapter.generateIdForRecord(this, modelName, properties);
4165
+ } else {
4166
+ properties.id = null;
4130
4167
  }
4168
+ }
4131
4169
 
4132
- // Coerce ID to a string
4133
- properties.id = coerceId(properties.id);
4134
- const resource = {
4135
- type: normalizedModelName,
4136
- id: properties.id
4137
- };
4138
- if (resource.id) {
4139
- const identifier = this.identifierCache.peekRecordIdentifier(resource);
4140
- assert(`The id ${String(properties.id)} has already been used with another '${normalizedModelName}' record.`, !identifier);
4141
- }
4142
- const identifier = this.identifierCache.createIdentifierForNewRecord(resource);
4143
- const cache = this.cache;
4144
- const createOptions = normalizeProperties(this, identifier, properties);
4145
- const resultProps = cache.clientDidCreate(identifier, createOptions);
4146
- record = this._instanceCache.getRecord(identifier, resultProps);
4147
- });
4170
+ // Coerce ID to a string
4171
+ properties.id = coerceId(properties.id);
4172
+ const resource = {
4173
+ type: normalizedModelName,
4174
+ id: properties.id
4175
+ };
4176
+ if (resource.id) {
4177
+ const identifier = this.identifierCache.peekRecordIdentifier(resource);
4178
+ assert(`The id ${String(properties.id)} has already been used with another '${normalizedModelName}' record.`, !identifier);
4179
+ }
4180
+ const identifier = this.identifierCache.createIdentifierForNewRecord(resource);
4181
+ const cache = this.cache;
4182
+ const createOptions = normalizeProperties(this, identifier, properties);
4183
+ const resultProps = cache.clientDidCreate(identifier, createOptions);
4184
+ record = this._instanceCache.getRecord(identifier, resultProps);
4148
4185
  });
4149
4186
  return record;
4150
4187
  }
@@ -4172,9 +4209,7 @@ class Store extends EmberObject {
4172
4209
  this._join(() => {
4173
4210
  cache.setIsDeleted(identifier, true);
4174
4211
  if (cache.isNew(identifier)) {
4175
- _backburner.join(() => {
4176
- this._instanceCache.unloadRecord(identifier);
4177
- });
4212
+ this._instanceCache.unloadRecord(identifier);
4178
4213
  }
4179
4214
  });
4180
4215
  }