@ember-data/store 4.8.0-alpha.3 → 4.8.0-alpha.4
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/caches/identifier-cache.ts +31 -39
- package/addon/-private/caches/instance-cache.ts +135 -192
- package/addon/-private/index.ts +3 -3
- package/addon/-private/legacy-model-support/record-reference.ts +12 -10
- package/addon/-private/legacy-model-support/schema-definition-service.ts +9 -4
- package/addon/-private/legacy-model-support/shim-model-class.ts +6 -2
- package/addon/-private/managers/record-array-manager.ts +5 -0
- package/addon/-private/managers/record-data-manager.ts +830 -0
- package/addon/-private/managers/record-data-store-wrapper.ts +283 -87
- package/addon/-private/managers/record-notification-manager.ts +17 -23
- package/addon/-private/network/fetch-manager.ts +275 -298
- package/addon/-private/network/snapshot.ts +25 -27
- package/addon/-private/record-arrays/record-array.ts +9 -1
- package/addon/-private/store-service.ts +251 -52
- package/addon/-private/utils/uuid-polyfill.ts +71 -0
- package/package.json +10 -6
|
@@ -4,6 +4,8 @@
|
|
|
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';
|
|
8
|
+
|
|
7
9
|
import { LOG_IDENTIFIERS } from '@ember-data/private-build-infra/debugging';
|
|
8
10
|
import type { ExistingResourceObject, ResourceIdentifierObject } from '@ember-data/types/q/ember-data-json-api';
|
|
9
11
|
import type {
|
|
@@ -34,6 +36,10 @@ export function isStableIdentifier(identifier: Object): identifier is StableReco
|
|
|
34
36
|
const isFastBoot = typeof FastBoot !== 'undefined';
|
|
35
37
|
const _crypto: Crypto = isFastBoot ? (FastBoot.require('crypto') as Crypto) : window.crypto;
|
|
36
38
|
|
|
39
|
+
if (macroCondition(getOwnConfig<{ polyfillUUID: boolean }>().polyfillUUID)) {
|
|
40
|
+
importSync('./utils/uuid-polyfill');
|
|
41
|
+
}
|
|
42
|
+
|
|
37
43
|
function uuidv4(): string {
|
|
38
44
|
return _crypto.randomUUID();
|
|
39
45
|
}
|
|
@@ -48,7 +54,6 @@ function freeze<T>(obj: T): T {
|
|
|
48
54
|
interface KeyOptions {
|
|
49
55
|
lid: IdentifierMap;
|
|
50
56
|
id: IdentifierMap;
|
|
51
|
-
_allIdentifiers: StableRecordIdentifier[];
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
type IdentifierMap = ConfidentDict<StableRecordIdentifier>;
|
|
@@ -115,19 +120,15 @@ if (DEBUG) {
|
|
|
115
120
|
@public
|
|
116
121
|
*/
|
|
117
122
|
export class IdentifierCache {
|
|
118
|
-
// Typescript still leaks private properties in the final
|
|
119
|
-
// compiled class, so we may want to move these from _underscore
|
|
120
|
-
// to a WeakMap to avoid leaking
|
|
121
|
-
// currently we leak this for test purposes
|
|
122
123
|
_cache = {
|
|
123
124
|
lids: Object.create(null) as IdentifierMap,
|
|
124
125
|
types: Object.create(null) as TypeMap,
|
|
125
126
|
};
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
declare _generate: GenerationMethod;
|
|
128
|
+
declare _update: UpdateMethod;
|
|
129
|
+
declare _forget: ForgetMethod;
|
|
130
|
+
declare _reset: ResetMethod;
|
|
131
|
+
declare _merge: MergeMethod;
|
|
131
132
|
|
|
132
133
|
constructor() {
|
|
133
134
|
// we cache the user configuredGenerationMethod at init because it must
|
|
@@ -156,12 +157,9 @@ export class IdentifierCache {
|
|
|
156
157
|
* @method _getRecordIdentifier
|
|
157
158
|
* @private
|
|
158
159
|
*/
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
shouldGenerate: false
|
|
163
|
-
): StableRecordIdentifier | undefined;
|
|
164
|
-
private _getRecordIdentifier(
|
|
160
|
+
_getRecordIdentifier(resource: ResourceIdentifierObject, shouldGenerate: true): StableRecordIdentifier;
|
|
161
|
+
_getRecordIdentifier(resource: ResourceIdentifierObject, shouldGenerate: false): StableRecordIdentifier | undefined;
|
|
162
|
+
_getRecordIdentifier(
|
|
165
163
|
resource: ResourceIdentifierObject,
|
|
166
164
|
shouldGenerate: boolean = false
|
|
167
165
|
): StableRecordIdentifier | undefined {
|
|
@@ -169,7 +167,7 @@ export class IdentifierCache {
|
|
|
169
167
|
if (isStableIdentifier(resource)) {
|
|
170
168
|
if (DEBUG) {
|
|
171
169
|
// TODO should we instead just treat this case as a new generation skipping the short circuit?
|
|
172
|
-
if (!(resource.lid
|
|
170
|
+
if (!(this._cache.lids[resource.lid] !== undefined) || this._cache.lids[resource.lid] !== resource) {
|
|
173
171
|
throw new Error(`The supplied identifier ${resource} does not belong to this store instance`);
|
|
174
172
|
}
|
|
175
173
|
}
|
|
@@ -197,7 +195,7 @@ export class IdentifierCache {
|
|
|
197
195
|
}
|
|
198
196
|
|
|
199
197
|
if (shouldGenerate === false) {
|
|
200
|
-
if (!(
|
|
198
|
+
if (!(resource as ExistingResourceObject).type || !(resource as ExistingResourceObject).id) {
|
|
201
199
|
return;
|
|
202
200
|
}
|
|
203
201
|
}
|
|
@@ -252,7 +250,7 @@ export class IdentifierCache {
|
|
|
252
250
|
if (DEBUG) {
|
|
253
251
|
// realistically if you hit this it means you changed `type` :/
|
|
254
252
|
// TODO consider how to handle type change assertions more gracefully
|
|
255
|
-
if (identifier.lid
|
|
253
|
+
if (this._cache.lids[identifier.lid] !== undefined) {
|
|
256
254
|
throw new Error(`You should not change the <type> of a RecordIdentifier`);
|
|
257
255
|
}
|
|
258
256
|
}
|
|
@@ -262,9 +260,6 @@ export class IdentifierCache {
|
|
|
262
260
|
// TODO consider having the `lid` cache be
|
|
263
261
|
// one level up
|
|
264
262
|
keyOptions.lid[identifier.lid] = identifier;
|
|
265
|
-
// TODO exists temporarily to support `peekAll`
|
|
266
|
-
// but likely to move
|
|
267
|
-
keyOptions._allIdentifiers.push(identifier);
|
|
268
263
|
|
|
269
264
|
if (LOG_IDENTIFIERS && shouldGenerate) {
|
|
270
265
|
// eslint-disable-next-line no-console
|
|
@@ -360,7 +355,7 @@ export class IdentifierCache {
|
|
|
360
355
|
|
|
361
356
|
// populate our unique table
|
|
362
357
|
if (DEBUG) {
|
|
363
|
-
if (identifier.lid
|
|
358
|
+
if (this._cache.lids[identifier.lid] !== undefined) {
|
|
364
359
|
throw new Error(`The lid generated for the new record is not unique as it matches an existing identifier`);
|
|
365
360
|
}
|
|
366
361
|
}
|
|
@@ -368,9 +363,6 @@ export class IdentifierCache {
|
|
|
368
363
|
|
|
369
364
|
// populate the type+lid cache
|
|
370
365
|
keyOptions.lid[newLid] = identifier;
|
|
371
|
-
// ensure a peekAll sees our new identifier too
|
|
372
|
-
// TODO move this outta here?
|
|
373
|
-
keyOptions._allIdentifiers.push(identifier);
|
|
374
366
|
|
|
375
367
|
if (LOG_IDENTIFIERS) {
|
|
376
368
|
// eslint-disable-next-line no-console
|
|
@@ -405,13 +397,17 @@ export class IdentifierCache {
|
|
|
405
397
|
updateRecordIdentifier(identifierObject: RecordIdentifier, data: ResourceData): StableRecordIdentifier {
|
|
406
398
|
let identifier = this.getOrCreateRecordIdentifier(identifierObject);
|
|
407
399
|
|
|
408
|
-
let newId =
|
|
400
|
+
let newId =
|
|
401
|
+
(data as ExistingResourceObject).id !== undefined ? coerceId((data as ExistingResourceObject).id) : null;
|
|
409
402
|
let existingIdentifier = detectMerge(this._cache.types, identifier, data, newId, this._cache.lids);
|
|
410
403
|
|
|
411
404
|
if (!existingIdentifier) {
|
|
412
405
|
// If the incoming type does not match the identifier type, we need to create an identifier for the incoming
|
|
413
406
|
// data so we can merge the incoming data with the existing identifier, see #7325 and #7363
|
|
414
|
-
if (
|
|
407
|
+
if (
|
|
408
|
+
(data as ExistingResourceObject).type &&
|
|
409
|
+
identifier.type !== normalizeModelName((data as ExistingResourceObject).type)
|
|
410
|
+
) {
|
|
415
411
|
let incomingDataResource = { ...data };
|
|
416
412
|
// Need to strip the lid from the incomingData in order force a new identifier creation
|
|
417
413
|
delete incomingDataResource.lid;
|
|
@@ -455,7 +451,7 @@ export class IdentifierCache {
|
|
|
455
451
|
keyOptions.id[newId] = identifier;
|
|
456
452
|
|
|
457
453
|
if (id !== null) {
|
|
458
|
-
|
|
454
|
+
keyOptions.id[id] = undefined as unknown as StableRecordIdentifier;
|
|
459
455
|
}
|
|
460
456
|
} else if (LOG_IDENTIFIERS) {
|
|
461
457
|
// eslint-disable-next-line no-console
|
|
@@ -511,13 +507,10 @@ export class IdentifierCache {
|
|
|
511
507
|
let identifier = this.getOrCreateRecordIdentifier(identifierObject);
|
|
512
508
|
let keyOptions = getTypeIndex(this._cache.types, identifier.type);
|
|
513
509
|
if (identifier.id !== null) {
|
|
514
|
-
|
|
510
|
+
keyOptions.id[identifier.id] = undefined as unknown as StableRecordIdentifier;
|
|
515
511
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
let index = keyOptions._allIdentifiers.indexOf(identifier);
|
|
520
|
-
keyOptions._allIdentifiers.splice(index, 1);
|
|
512
|
+
this._cache.lids[identifier.lid] = undefined as unknown as StableRecordIdentifier;
|
|
513
|
+
keyOptions.lid[identifier.lid] = undefined as unknown as StableRecordIdentifier;
|
|
521
514
|
|
|
522
515
|
IDENTIFIERS.delete(identifierObject);
|
|
523
516
|
this._forget(identifier, 'record');
|
|
@@ -539,7 +532,6 @@ function getTypeIndex(typeMap: TypeMap, type: string): KeyOptions {
|
|
|
539
532
|
typeIndex = {
|
|
540
533
|
lid: Object.create(null),
|
|
541
534
|
id: Object.create(null),
|
|
542
|
-
_allIdentifiers: [],
|
|
543
535
|
};
|
|
544
536
|
typeMap[type] = typeIndex;
|
|
545
537
|
}
|
|
@@ -643,8 +635,8 @@ function performRecordIdentifierUpdate(identifier: StableRecordIdentifier, data:
|
|
|
643
635
|
// for the multiple-cache-key scenario we "could"
|
|
644
636
|
// use a heuristic to guess the best id for display
|
|
645
637
|
// (usually when `data.id` is available and `data.attributes` is not)
|
|
646
|
-
if (
|
|
647
|
-
identifier.id = coerceId(data.id);
|
|
638
|
+
if ((data as ExistingResourceObject).id !== undefined) {
|
|
639
|
+
identifier.id = coerceId((data as ExistingResourceObject).id);
|
|
648
640
|
}
|
|
649
641
|
}
|
|
650
642
|
|
|
@@ -662,7 +654,7 @@ function detectMerge(
|
|
|
662
654
|
|
|
663
655
|
return existingIdentifier !== undefined ? existingIdentifier : false;
|
|
664
656
|
} else {
|
|
665
|
-
let newType =
|
|
657
|
+
let newType = (data as ExistingResourceObject).type && normalizeModelName((data as ExistingResourceObject).type);
|
|
666
658
|
|
|
667
659
|
// If the ids and type are the same but lid is not the same, we should trigger a merge of the identifiers
|
|
668
660
|
if (id !== null && id === newId && newType === type && data.lid && data.lid !== lid) {
|