@ember-data/store 4.8.0-alpha.6 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md CHANGED
@@ -1,6 +1,8 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019
3
+ Copyright (C) 2017-2022 Ember.js contributors
4
+ Portions Copyright (C) 2011-2017 Tilde, Inc. and contributors.
5
+ Portions Copyright (C) 2011 LivingSocial Inc.
4
6
 
5
7
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
8
 
@@ -4,7 +4,7 @@
4
4
  import { assert, warn } from '@ember/debug';
5
5
  import { DEBUG } from '@glimmer/env';
6
6
 
7
- import { getOwnConfig, importSync, macroCondition } from '@embroider/macros';
7
+ import { getOwnConfig, macroCondition } from '@embroider/macros';
8
8
 
9
9
  import { LOG_IDENTIFIERS } from '@ember-data/private-build-infra/debugging';
10
10
  import type { ExistingResourceObject, ResourceIdentifierObject } from '@ember-data/types/q/ember-data-json-api';
@@ -25,6 +25,7 @@ import coerceId from '../utils/coerce-id';
25
25
  import { DEBUG_CLIENT_ORIGINATED, DEBUG_IDENTIFIER_BUCKET } from '../utils/identifer-debug-consts';
26
26
  import isNonEmptyString from '../utils/is-non-empty-string';
27
27
  import normalizeModelName from '../utils/normalize-model-name';
28
+ import installPolyfill from '../utils/uuid-polyfill';
28
29
 
29
30
  const IDENTIFIERS = new Set();
30
31
 
@@ -36,7 +37,7 @@ const isFastBoot = typeof FastBoot !== 'undefined';
36
37
  const _crypto: Crypto = isFastBoot ? (FastBoot.require('crypto') as Crypto) : window.crypto;
37
38
 
38
39
  if (macroCondition(getOwnConfig<{ polyfillUUID: boolean }>().polyfillUUID)) {
39
- importSync('./utils/uuid-polyfill');
40
+ installPolyfill();
40
41
  }
41
42
 
42
43
  function uuidv4(): string {
@@ -265,14 +266,16 @@ export class IdentifierCache {
265
266
  // one level up
266
267
  keyOptions.lid.set(identifier.lid, identifier);
267
268
 
268
- if (LOG_IDENTIFIERS && shouldGenerate) {
269
- // eslint-disable-next-line no-console
270
- console.log(`Identifiers: generated ${String(identifier)} for`, resource);
271
- if (resource[DEBUG_IDENTIFIER_BUCKET]) {
269
+ if (LOG_IDENTIFIERS) {
270
+ if (shouldGenerate) {
272
271
  // eslint-disable-next-line no-console
273
- console.trace(
274
- `[WARNING] Identifiers: generated a new identifier from a previously used identifier. This is likely a bug.`
275
- );
272
+ console.log(`Identifiers: generated ${String(identifier)} for`, resource);
273
+ if (resource[DEBUG_IDENTIFIER_BUCKET]) {
274
+ // eslint-disable-next-line no-console
275
+ console.trace(
276
+ `[WARNING] Identifiers: generated a new identifier from a previously used identifier. This is likely a bug.`
277
+ );
278
+ }
276
279
  }
277
280
  }
278
281
  }
@@ -7,7 +7,8 @@ import { resolve } from 'rsvp';
7
7
  import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
8
8
  import { LOG_INSTANCE_CACHE } from '@ember-data/private-build-infra/debugging';
9
9
  import { DEPRECATE_V1_RECORD_DATA, DEPRECATE_V1CACHE_STORE_APIS } from '@ember-data/private-build-infra/deprecations';
10
- import type { Graph, peekGraph } from '@ember-data/record-data/-private/graph/index';
10
+ import type { Graph } from '@ember-data/record-data/-private/graph/graph';
11
+ import type { peekGraph } from '@ember-data/record-data/-private/graph/index';
11
12
  import type {
12
13
  ExistingResourceIdentifierObject,
13
14
  ExistingResourceObject,
@@ -83,8 +84,10 @@ export function recordIdentifierFor(record: RecordInstance): StableRecordIdentif
83
84
  }
84
85
 
85
86
  export function setRecordIdentifier(record: RecordInstance, identifier: StableRecordIdentifier): void {
86
- if (DEBUG && RecordCache.has(record) && RecordCache.get(record) !== identifier) {
87
- throw new Error(`${String(record)} was already assigned an identifier`);
87
+ if (DEBUG) {
88
+ if (RecordCache.has(record) && RecordCache.get(record) !== identifier) {
89
+ throw new Error(`${String(record)} was already assigned an identifier`);
90
+ }
88
91
  }
89
92
 
90
93
  /*
@@ -128,44 +131,6 @@ export class InstanceCache {
128
131
  reference: new WeakMap<StableRecordIdentifier, RecordReference>(),
129
132
  };
130
133
 
131
- recordIsLoaded(identifier: StableRecordIdentifier, filterDeleted: boolean = false) {
132
- const recordData = this.__instances.recordData.get(identifier);
133
- if (!recordData) {
134
- return false;
135
- }
136
- const isNew = recordData.isNew(identifier);
137
- const isEmpty = recordData.isEmpty(identifier);
138
-
139
- // if we are new we must consider ourselves loaded
140
- if (isNew) {
141
- return !recordData.isDeleted(identifier);
142
- }
143
- // even if we have a past request, if we are now empty we are not loaded
144
- // typically this is true after an unloadRecord call
145
-
146
- // if we are not empty, not new && we have a fulfilled request then we are loaded
147
- // we should consider allowing for something to be loaded that is simply "not empty".
148
- // which is how RecordState currently handles this case; however, RecordState is buggy
149
- // in that it does not account for unloading.
150
- return filterDeleted && recordData.isDeletionCommitted(identifier) ? false : !isEmpty;
151
-
152
- /*
153
- const req = this.store.getRequestStateService();
154
- const fulfilled = req.getLastRequestForRecord(identifier);
155
- const isLocallyLoaded = !isEmpty;
156
- const isLoading =
157
- !isLocallyLoaded &&
158
- fulfilled === null &&
159
- req.getPendingRequestsForRecord(identifier).some((req) => req.type === 'query');
160
-
161
- if (isEmpty || (filterDeleted && recordData.isDeletionCommitted(identifier)) || isLoading) {
162
- return false;
163
- }
164
-
165
- return true;
166
- */
167
- }
168
-
169
134
  constructor(store: Store) {
170
135
  this.store = store;
171
136
 
@@ -178,25 +143,24 @@ export class InstanceCache {
178
143
 
179
144
  store.identifierCache.__configureMerge(
180
145
  (identifier: StableRecordIdentifier, matchedIdentifier: StableRecordIdentifier, resourceData) => {
181
- let intendedIdentifier = identifier;
146
+ let keptIdentifier = identifier;
182
147
  if (identifier.id !== matchedIdentifier.id) {
183
- intendedIdentifier =
184
- 'id' in resourceData && identifier.id === resourceData.id ? identifier : matchedIdentifier;
148
+ keptIdentifier = 'id' in resourceData && identifier.id === resourceData.id ? identifier : matchedIdentifier;
185
149
  } else if (identifier.type !== matchedIdentifier.type) {
186
- intendedIdentifier =
150
+ keptIdentifier =
187
151
  'type' in resourceData && identifier.type === resourceData.type ? identifier : matchedIdentifier;
188
152
  }
189
- let altIdentifier = identifier === intendedIdentifier ? matchedIdentifier : identifier;
153
+ let staleIdentifier = identifier === keptIdentifier ? matchedIdentifier : identifier;
190
154
 
191
155
  // check for duplicate entities
192
- let imHasRecord = this.__instances.record.has(intendedIdentifier);
193
- let otherHasRecord = this.__instances.record.has(altIdentifier);
194
- let imRecordData = this.__instances.recordData.get(intendedIdentifier) || null;
195
- let otherRecordData = this.__instances.recordData.get(altIdentifier) || null;
156
+ let keptHasRecord = this.__instances.record.has(keptIdentifier);
157
+ let staleHasRecord = this.__instances.record.has(staleIdentifier);
158
+ let keptRecordData = this.__instances.recordData.get(keptIdentifier) || null;
159
+ let staleRecordData = this.__instances.recordData.get(staleIdentifier) || null;
196
160
 
197
161
  // we cannot merge entities when both have records
198
162
  // (this may not be strictly true, we could probably swap the recordData the record points at)
199
- if (imHasRecord && otherHasRecord) {
163
+ if (keptHasRecord && staleHasRecord) {
200
164
  // TODO we probably don't need to throw these errors anymore
201
165
  // we can probably just "swap" what data source the abandoned
202
166
  // record points at so long as
@@ -210,7 +174,7 @@ export class InstanceCache {
210
174
  }:${String(matchedIdentifier.id)} (${matchedIdentifier.lid})'`
211
175
  );
212
176
  }
213
- // TODO @runspired determine when this is even possible
177
+
214
178
  assert(
215
179
  `Failed to update the RecordIdentifier '${identifier.type}:${String(identifier.id)} (${
216
180
  identifier.lid
@@ -220,33 +184,26 @@ export class InstanceCache {
220
184
  );
221
185
  }
222
186
 
223
- // remove "other" from cache
224
- if (otherHasRecord) {
225
- // TODO probably need to release other things
187
+ let recordData = keptRecordData || staleRecordData;
188
+
189
+ if (recordData) {
190
+ recordData.sync({
191
+ op: 'mergeIdentifiers',
192
+ record: staleIdentifier,
193
+ value: keptIdentifier,
194
+ });
195
+ } else if (HAS_RECORD_DATA_PACKAGE) {
196
+ // TODO notify cache always, this requires it always being a singleton
197
+ // and not ever specific to one record-data
198
+ this.store.__private_singleton_recordData?.sync({
199
+ op: 'mergeIdentifiers',
200
+ record: staleIdentifier,
201
+ value: keptIdentifier,
202
+ });
226
203
  }
227
204
 
228
- if (imRecordData === null && otherRecordData === null) {
229
- // nothing more to do
230
- return intendedIdentifier;
231
-
232
- // only the other has a RecordData
233
- // OR only the other has a Record
234
- } else if (
235
- (imRecordData === null && otherRecordData !== null) ||
236
- (imRecordData && !imHasRecord && otherRecordData && otherHasRecord)
237
- ) {
238
- if (imRecordData) {
239
- // TODO check if we are retained in any async relationships
240
- // TODO probably need to release other things
241
- // im.destroy();
242
- }
243
- imRecordData = otherRecordData!;
244
- // TODO do we need to notify the id change?
245
- // TODO swap recordIdentifierFor result?
246
-
247
- // just use im
248
- } else {
249
- // otherIm.destroy();
205
+ if (staleRecordData === null) {
206
+ return keptIdentifier;
250
207
  }
251
208
 
252
209
  /*
@@ -259,7 +216,8 @@ export class InstanceCache {
259
216
  }
260
217
  */
261
218
 
262
- return intendedIdentifier;
219
+ this.unloadRecord(staleIdentifier);
220
+ return keptIdentifier;
263
221
  }
264
222
  );
265
223
  }
@@ -304,8 +262,8 @@ export class InstanceCache {
304
262
  getRecordData(identifier: StableRecordIdentifier): RecordData {
305
263
  let recordData = this.__instances.recordData.get(identifier);
306
264
 
307
- if (!recordData) {
308
- if (DEPRECATE_V1CACHE_STORE_APIS && this.store.createRecordDataFor.length > 2) {
265
+ if (DEPRECATE_V1CACHE_STORE_APIS) {
266
+ if (!recordData && this.store.createRecordDataFor.length > 2) {
309
267
  deprecate(
310
268
  `Store.createRecordDataFor(<type>, <id>, <lid>, <storeWrapper>) has been deprecated in favor of Store.createRecordDataFor(<identifier>, <storeWrapper>)`,
311
269
  false,
@@ -313,7 +271,7 @@ export class InstanceCache {
313
271
  id: 'ember-data:deprecate-v1cache-store-apis',
314
272
  for: 'ember-data',
315
273
  until: '5.0',
316
- since: { enabled: '4.8', available: '4.8' },
274
+ since: { enabled: '4.7', available: '4.7' },
317
275
  }
318
276
  );
319
277
  let recordDataInstance = this.store.createRecordDataFor(
@@ -329,19 +287,22 @@ export class InstanceCache {
329
287
  recordData = this.__cacheManager =
330
288
  this.__cacheManager || new NonSingletonRecordDataManager(this.store, recordDataInstance, identifier);
331
289
  }
290
+ }
291
+ }
292
+
293
+ if (!recordData) {
294
+ let recordDataInstance = this.store.createRecordDataFor(identifier, this._storeWrapper);
295
+ if (DEPRECATE_V1_RECORD_DATA) {
296
+ recordData = new NonSingletonRecordDataManager(this.store, recordDataInstance, identifier);
332
297
  } else {
333
- let recordDataInstance = this.store.createRecordDataFor(identifier, this._storeWrapper);
334
- if (DEPRECATE_V1_RECORD_DATA) {
335
- recordData = new NonSingletonRecordDataManager(this.store, recordDataInstance, identifier);
298
+ if (DEBUG) {
299
+ recordData = this.__cacheManager = this.__cacheManager || new SingletonRecordDataManager();
300
+ (recordData as SingletonRecordDataManager)._addRecordData(identifier, recordDataInstance as RecordData);
336
301
  } else {
337
- if (DEBUG) {
338
- recordData = this.__cacheManager = this.__cacheManager || new SingletonRecordDataManager();
339
- (recordData as SingletonRecordDataManager)._addRecordData(identifier, recordDataInstance as RecordData);
340
- } else {
341
- recordData = recordDataInstance as RecordData;
342
- }
302
+ recordData = recordDataInstance as RecordData;
343
303
  }
344
304
  }
305
+
345
306
  setRecordDataFor(identifier, recordData);
346
307
 
347
308
  this.__instances.recordData.set(identifier, recordData);
@@ -365,6 +326,44 @@ export class InstanceCache {
365
326
  return reference;
366
327
  }
367
328
 
329
+ recordIsLoaded(identifier: StableRecordIdentifier, filterDeleted: boolean = false) {
330
+ const recordData = this.__instances.recordData.get(identifier);
331
+ if (!recordData) {
332
+ return false;
333
+ }
334
+ const isNew = recordData.isNew(identifier);
335
+ const isEmpty = recordData.isEmpty(identifier);
336
+
337
+ // if we are new we must consider ourselves loaded
338
+ if (isNew) {
339
+ return !recordData.isDeleted(identifier);
340
+ }
341
+ // even if we have a past request, if we are now empty we are not loaded
342
+ // typically this is true after an unloadRecord call
343
+
344
+ // if we are not empty, not new && we have a fulfilled request then we are loaded
345
+ // we should consider allowing for something to be loaded that is simply "not empty".
346
+ // which is how RecordState currently handles this case; however, RecordState is buggy
347
+ // in that it does not account for unloading.
348
+ return filterDeleted && recordData.isDeletionCommitted(identifier) ? false : !isEmpty;
349
+
350
+ /*
351
+ const req = this.store.getRequestStateService();
352
+ const fulfilled = req.getLastRequestForRecord(identifier);
353
+ const isLocallyLoaded = !isEmpty;
354
+ const isLoading =
355
+ !isLocallyLoaded &&
356
+ fulfilled === null &&
357
+ req.getPendingRequestsForRecord(identifier).some((req) => req.type === 'query');
358
+
359
+ if (isEmpty || (filterDeleted && recordData.isDeletionCommitted(identifier)) || isLoading) {
360
+ return false;
361
+ }
362
+
363
+ return true;
364
+ */
365
+ }
366
+
368
367
  createSnapshot(identifier: StableRecordIdentifier, options: FindOptions = {}): Snapshot {
369
368
  return new Snapshot(options, identifier, this.store);
370
369
  }
@@ -30,7 +30,7 @@ export function normalizeModelName(modelName: string) {
30
30
  id: 'ember-data:deprecate-normalize-modelname-helper',
31
31
  for: 'ember-data',
32
32
  until: '5.0',
33
- since: { available: '4.8', enabled: '4.8' },
33
+ since: { available: '4.7', enabled: '4.7' },
34
34
  }
35
35
  );
36
36
  return _normalize(modelName);
@@ -39,18 +39,22 @@ export class DSModelSchemaDefinitionService {
39
39
  // Following the existing RD implementation
40
40
  attributesDefinitionFor(identifier: RecordIdentifier | { type: string }): AttributesSchema {
41
41
  let modelName, attributes;
42
- if (DEPRECATE_STRING_ARG_SCHEMAS && typeof identifier === 'string') {
43
- deprecate(
44
- `attributesDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`,
45
- false,
46
- {
47
- id: 'ember-data:deprecate-string-arg-schemas',
48
- for: 'ember-data',
49
- until: '5.0',
50
- since: { enabled: '4.5', available: '4.5' },
51
- }
52
- );
53
- modelName = identifier;
42
+ if (DEPRECATE_STRING_ARG_SCHEMAS) {
43
+ if (typeof identifier === 'string') {
44
+ deprecate(
45
+ `attributesDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`,
46
+ false,
47
+ {
48
+ id: 'ember-data:deprecate-string-arg-schemas',
49
+ for: 'ember-data',
50
+ until: '5.0',
51
+ since: { enabled: '4.5', available: '4.5' },
52
+ }
53
+ );
54
+ modelName = identifier;
55
+ } else {
56
+ modelName = identifier.type;
57
+ }
54
58
  } else {
55
59
  modelName = identifier.type;
56
60
  }
@@ -72,18 +76,22 @@ export class DSModelSchemaDefinitionService {
72
76
  // Following the existing RD implementation
73
77
  relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
74
78
  let modelName, relationships;
75
- if (DEPRECATE_STRING_ARG_SCHEMAS && typeof identifier === 'string') {
76
- deprecate(
77
- `relationshipsDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`,
78
- false,
79
- {
80
- id: 'ember-data:deprecate-string-arg-schemas',
81
- for: 'ember-data',
82
- until: '5.0',
83
- since: { enabled: '4.5', available: '4.5' },
84
- }
85
- );
86
- modelName = identifier;
79
+ if (DEPRECATE_STRING_ARG_SCHEMAS) {
80
+ if (typeof identifier === 'string') {
81
+ deprecate(
82
+ `relationshipsDefinitionFor expects either a record identifier or an argument of shape { type: string }, received a string.`,
83
+ false,
84
+ {
85
+ id: 'ember-data:deprecate-string-arg-schemas',
86
+ for: 'ember-data',
87
+ until: '5.0',
88
+ since: { enabled: '4.5', available: '4.5' },
89
+ }
90
+ );
91
+ modelName = identifier;
92
+ } else {
93
+ modelName = identifier.type;
94
+ }
87
95
  } else {
88
96
  modelName = identifier.type;
89
97
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  @module @ember-data/store
3
3
  */
4
+ import { addToTransaction } from '@ember-data/tracking/-private';
4
5
  import type { CollectionResourceDocument } from '@ember-data/types/q/ember-data-json-api';
5
6
  import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
6
7
  import type { Dict } from '@ember-data/types/q/utils';
@@ -60,7 +61,7 @@ export function fastPush<T>(target: T[], source: T[]) {
60
61
  let newLength = source.length;
61
62
  while (newLength - startLength > SLICE_BATCH_SIZE) {
62
63
  // eslint-disable-next-line prefer-spread
63
- target.push.apply(target, source.slice(startLength, SLICE_BATCH_SIZE));
64
+ target.push.apply(target, source.slice(startLength, startLength + SLICE_BATCH_SIZE));
64
65
  startLength += SLICE_BATCH_SIZE;
65
66
  }
66
67
  // eslint-disable-next-line prefer-spread
@@ -167,14 +168,16 @@ class RecordArrayManager {
167
168
  return array;
168
169
  }
169
170
 
170
- dirtyArray(array: IdentifierArray): void {
171
+ dirtyArray(array: IdentifierArray, delta: number): void {
171
172
  if (array === FAKE_ARR) {
172
173
  return;
173
174
  }
174
175
  let tag = array[IDENTIFIER_ARRAY_TAG];
175
176
  if (!tag.shouldReset) {
176
177
  tag.shouldReset = true;
177
- tag.ref = null;
178
+ addToTransaction(tag);
179
+ } else if (delta > 0 && tag.t) {
180
+ addToTransaction(tag);
178
181
  }
179
182
  }
180
183
 
@@ -257,9 +260,7 @@ class RecordArrayManager {
257
260
  } else {
258
261
  changes.set(identifier, 'add');
259
262
 
260
- if (changes.size === 1) {
261
- this.dirtyArray(array);
262
- }
263
+ this.dirtyArray(array, changes.size);
263
264
  }
264
265
  });
265
266
  }
@@ -275,9 +276,7 @@ class RecordArrayManager {
275
276
  } else {
276
277
  changes.set(identifier, 'del');
277
278
 
278
- if (changes.size === 1) {
279
- this.dirtyArray(array);
280
- }
279
+ this.dirtyArray(array, changes.size);
281
280
  }
282
281
  });
283
282
  }
@@ -6,7 +6,7 @@ import type {
6
6
  SingleResourceRelationship,
7
7
  } from '@ember-data/types/q/ember-data-json-api';
8
8
  import type { StableRecordIdentifier } from '@ember-data/types/q/identifier';
9
- import type { ChangedAttributesHash, RecordData, RecordDataV1 } from '@ember-data/types/q/record-data';
9
+ import type { ChangedAttributesHash, MergeOperation, RecordData, RecordDataV1 } from '@ember-data/types/q/record-data';
10
10
  import type { JsonApiResource, JsonApiValidationError } from '@ember-data/types/q/record-data-json-api';
11
11
  import type { Dict } from '@ember-data/types/q/utils';
12
12
 
@@ -76,7 +76,7 @@ export class NonSingletonRecordDataManager implements RecordData {
76
76
  {
77
77
  id: 'ember-data:deprecate-v1-cache',
78
78
  until: '5.0',
79
- since: { available: '4.8', enabled: '4.8' },
79
+ since: { available: '4.7', enabled: '4.7' },
80
80
  for: 'ember-data',
81
81
  }
82
82
  );
@@ -128,6 +128,25 @@ export class NonSingletonRecordDataManager implements RecordData {
128
128
  return recordData.pushData(identifier, data, hasRecord);
129
129
  }
130
130
 
131
+ /**
132
+ * Perform an operation on the cache to update the remote state.
133
+ *
134
+ * Note: currently the only valid operation is a MergeOperation
135
+ * which occurs when a collision of identifiers is detected.
136
+ *
137
+ * @method sync
138
+ * @public
139
+ * @param op the operation to perform
140
+ * @returns {void}
141
+ */
142
+ sync(op: MergeOperation): void {
143
+ const recordData = this.#recordData;
144
+ if (this.#isDeprecated(recordData)) {
145
+ return;
146
+ }
147
+ recordData.sync(op);
148
+ }
149
+
131
150
  /**
132
151
  * Update resource data with a local mutation. Currently supports operations
133
152
  * on relationships only.
@@ -395,7 +414,7 @@ export class NonSingletonRecordDataManager implements RecordData {
395
414
  * @method hasChangedAttributes
396
415
  * @public
397
416
  * @deprecated
398
- * @returns
417
+ * @returns {boolean}
399
418
  */
400
419
  hasChangedAttributes(): boolean {
401
420
  const recordData = this.#recordData;
@@ -410,7 +429,7 @@ export class NonSingletonRecordDataManager implements RecordData {
410
429
  * @method hasChangedAttrs
411
430
  * @public
412
431
  * @param identifier
413
- * @returns
432
+ * @returns {boolean}
414
433
  */
415
434
  hasChangedAttrs(identifier: StableRecordIdentifier): boolean {
416
435
  const recordData = this.#recordData;
@@ -740,6 +759,10 @@ export class SingletonRecordDataManager implements RecordData {
740
759
  return this.#recordData(identifier).pushData(identifier, data, hasRecord);
741
760
  }
742
761
 
762
+ sync(op: MergeOperation): void {
763
+ this.#recordData(op.record).sync(op);
764
+ }
765
+
743
766
  clientDidCreate(identifier: StableRecordIdentifier, options?: Dict<unknown>): Dict<unknown> {
744
767
  return this.#recordData(identifier).clientDidCreate(identifier, options);
745
768
  }
@@ -99,7 +99,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
99
99
  id: 'ember-data:deprecate-v1cache-store-apis',
100
100
  for: 'ember-data',
101
101
  until: '5.0',
102
- since: { enabled: '4.8', available: '4.8' },
102
+ since: { enabled: '4.7', available: '4.7' },
103
103
  });
104
104
  }
105
105
  const resource = constructResource(type, id, lid);
@@ -117,7 +117,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
117
117
  id: 'ember-data:deprecate-v1cache-store-apis',
118
118
  for: 'ember-data',
119
119
  until: '5.0',
120
- since: { enabled: '4.8', available: '4.8' },
120
+ since: { enabled: '4.7', available: '4.7' },
121
121
  }
122
122
  );
123
123
  }
@@ -133,7 +133,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
133
133
  id: 'ember-data:deprecate-v1cache-store-apis',
134
134
  for: 'ember-data',
135
135
  until: '5.0',
136
- since: { enabled: '4.8', available: '4.8' },
136
+ since: { enabled: '4.7', available: '4.7' },
137
137
  }
138
138
  );
139
139
  }
@@ -152,7 +152,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
152
152
  id: 'ember-data:deprecate-v1cache-store-apis',
153
153
  for: 'ember-data',
154
154
  until: '5.0',
155
- since: { enabled: '4.8', available: '4.8' },
155
+ since: { enabled: '4.7', available: '4.7' },
156
156
  });
157
157
  }
158
158
  const resource = constructResource(type, id, lid);
@@ -169,7 +169,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
169
169
  id: 'ember-data:deprecate-v1cache-store-apis',
170
170
  for: 'ember-data',
171
171
  until: '5.0',
172
- since: { enabled: '4.8', available: '4.8' },
172
+ since: { enabled: '4.7', available: '4.7' },
173
173
  });
174
174
  }
175
175
  const resource = constructResource(type, id, lid);
@@ -185,7 +185,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
185
185
  id: 'ember-data:deprecate-v1cache-store-apis',
186
186
  for: 'ember-data',
187
187
  until: '5.0',
188
- since: { enabled: '4.8', available: '4.8' },
188
+ since: { enabled: '4.7', available: '4.7' },
189
189
  });
190
190
  }
191
191
  const resource = constructResource(type, id, lid);
@@ -202,7 +202,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
202
202
  id: 'ember-data:deprecate-v1cache-store-apis',
203
203
  for: 'ember-data',
204
204
  until: '5.0',
205
- since: { enabled: '4.8', available: '4.8' },
205
+ since: { enabled: '4.7', available: '4.7' },
206
206
  });
207
207
  }
208
208
  const resource = constructResource(type, id, lid);
@@ -277,7 +277,7 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
277
277
  id: 'ember-data:deprecate-v1cache-store-apis',
278
278
  for: 'ember-data',
279
279
  until: '5.0',
280
- since: { enabled: '4.8', available: '4.8' },
280
+ since: { enabled: '4.7', available: '4.7' },
281
281
  });
282
282
  }
283
283
  const resource = constructResource(type, id, lid);
@@ -297,19 +297,23 @@ class LegacyWrapper implements LegacyRecordDataStoreWrapper {
297
297
  disconnectRecord(type: StableRecordIdentifier): void;
298
298
  disconnectRecord(type: string | StableRecordIdentifier, id?: string | null, lid?: string | null): void {
299
299
  let identifier: StableRecordIdentifier;
300
- if (DEPRECATE_V1CACHE_STORE_APIS && typeof type === 'string') {
301
- deprecate(
302
- `StoreWrapper.disconnectRecord(<type>) has been deprecated in favor of StoreWrapper.disconnectRecord(<identifier>)`,
303
- false,
304
- {
305
- id: 'ember-data:deprecate-v1cache-store-apis',
306
- for: 'ember-data',
307
- until: '5.0',
308
- since: { enabled: '4.8', available: '4.8' },
309
- }
310
- );
311
- let resource = constructResource(type, id, lid) as RecordIdentifier;
312
- identifier = this.identifierCache.peekRecordIdentifier(resource)!;
300
+ if (DEPRECATE_V1CACHE_STORE_APIS) {
301
+ if (typeof type === 'string') {
302
+ deprecate(
303
+ `StoreWrapper.disconnectRecord(<type>) has been deprecated in favor of StoreWrapper.disconnectRecord(<identifier>)`,
304
+ false,
305
+ {
306
+ id: 'ember-data:deprecate-v1cache-store-apis',
307
+ for: 'ember-data',
308
+ until: '5.0',
309
+ since: { enabled: '4.7', available: '4.7' },
310
+ }
311
+ );
312
+ let resource = constructResource(type, id, lid) as RecordIdentifier;
313
+ identifier = this.identifierCache.peekRecordIdentifier(resource)!;
314
+ } else {
315
+ identifier = type as StableRecordIdentifier;
316
+ }
313
317
  } else {
314
318
  identifier = type as StableRecordIdentifier;
315
319
  }
@@ -24,9 +24,11 @@ export interface NotificationCallback {
24
24
  // TODO this isn't importable anyway, remove and use a map on the manager?
25
25
  export function unsubscribe(token: UnsubscribeToken) {
26
26
  let identifier = Tokens.get(token);
27
- if (LOG_NOTIFICATIONS && !identifier) {
28
- // eslint-disable-next-line no-console
29
- console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
27
+ if (LOG_NOTIFICATIONS) {
28
+ if (!identifier) {
29
+ // eslint-disable-next-line no-console
30
+ console.log('Passed unknown unsubscribe token to unsubscribe', identifier);
31
+ }
30
32
  }
31
33
  if (identifier) {
32
34
  Tokens.delete(token);