@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.
@@ -0,0 +1,830 @@
1
+ import { assert } from '@ember/debug';
2
+
3
+ import { CollectionResourceRelationship, SingleResourceRelationship } from '@ember-data/types/q/ember-data-json-api';
4
+ import { StableRecordIdentifier } from '@ember-data/types/q/identifier';
5
+ import { ChangedAttributesHash, RecordData, RecordDataV1 } from '@ember-data/types/q/record-data';
6
+ import { JsonApiResource, JsonApiValidationError } from '@ember-data/types/q/record-data-json-api';
7
+ import { Dict } from '@ember-data/types/q/utils';
8
+
9
+ import { isStableIdentifier } from '../caches/identifier-cache';
10
+ import Store from '../store-service';
11
+
12
+ /**
13
+ * The RecordDataManager wraps a RecordData cache
14
+ * enforcing that only the public API surface area
15
+ * is exposed.
16
+ *
17
+ * This class is the the return value of both the
18
+ * `recordDataFor` function supplied to the store
19
+ * hook `instantiateRecord`, and the `recordDataFor`
20
+ * method on the `RecordDataStoreWrapper`. It is not
21
+ * directly instantiatable.
22
+ *
23
+ * It handles translating between cache versions when
24
+ * necessary, for instance when a Store is configured
25
+ * to use both a v1 and a v2 cache depending on some
26
+ * heuristic.
27
+ *
28
+ * Starting with the v2 spec, the cache is designed such
29
+ * that it may be implemented as a singleton. However,
30
+ * because the v1 spec was not designed for this whenever
31
+ * we encounter any v1 cache we must wrap all caches, even
32
+ * singletons, in non-singleton managers to preserve v1
33
+ * compatibility.
34
+ *
35
+ * To avoid this performance penalty being paid by all
36
+ * applications, singleton behavior may be opted-in via
37
+ * the configuration supplied to your Ember application
38
+ * at build time. This effectively removes support for
39
+ * v1 caches.
40
+ *
41
+ * ```js
42
+ * let app = new EmberApp(defaults, {
43
+ * emberData: {
44
+ * useSingletonManager: true
45
+ * },
46
+ * });
47
+ * ```
48
+ *
49
+ * @class RecordDataManager
50
+ * @public
51
+ */
52
+ export class NonSingletonRecordDataManager implements RecordData {
53
+ version: '2' = '2';
54
+
55
+ #store: Store;
56
+ #recordData: RecordData | RecordDataV1;
57
+ #identifier: StableRecordIdentifier;
58
+
59
+ get managedVersion() {
60
+ return this.#recordData.version || '1';
61
+ }
62
+
63
+ constructor(store: Store, recordData: RecordData | RecordDataV1, identifier: StableRecordIdentifier) {
64
+ this.#store = store;
65
+ this.#recordData = recordData;
66
+ this.#identifier = identifier;
67
+ }
68
+
69
+ #isDeprecated(recordData: RecordData | RecordDataV1): recordData is RecordDataV1 {
70
+ let version = recordData.version || '1';
71
+ return version !== this.version;
72
+ }
73
+
74
+ // Cache
75
+ // =====
76
+
77
+ /**
78
+ * Retrieve the identifier for this v1 recordData
79
+ *
80
+ * DEPRECATED Caches should not be assumed to be 1:1 with resources
81
+ *
82
+ * @method getResourceIdentifier
83
+ * @public
84
+ * @deprecated
85
+ */
86
+ getResourceIdentifier(): StableRecordIdentifier {
87
+ return this.#identifier;
88
+ }
89
+
90
+ /**
91
+ * Push resource data from a remote source into the cache for this identifier
92
+ *
93
+ * @method pushData
94
+ * @public
95
+ * @param identifier
96
+ * @param data
97
+ * @param hasRecord
98
+ * @returns {void | string[]} if `hasRecord` is true then calculated key changes should be returned
99
+ */
100
+ pushData(identifier: StableRecordIdentifier, data: JsonApiResource, hasRecord?: boolean): void | string[] {
101
+ const recordData = this.#recordData;
102
+ // called by something V1
103
+ if (!isStableIdentifier(identifier)) {
104
+ data = identifier as JsonApiResource;
105
+ hasRecord = data as boolean;
106
+ identifier = this.#identifier;
107
+ }
108
+ if (this.#isDeprecated(recordData)) {
109
+ return recordData.pushData(data, hasRecord);
110
+ }
111
+ return recordData.pushData(identifier, data, hasRecord);
112
+ }
113
+
114
+ /**
115
+ * [LIFECYLCE] Signal to the cache that a new record has been instantiated on the client
116
+ *
117
+ * It returns properties from options that should be set on the record during the create
118
+ * process. This return value behavior is deprecated.
119
+ *
120
+ * @method clientDidCreate
121
+ * @public
122
+ * @param identifier
123
+ * @param options
124
+ */
125
+ clientDidCreate(identifier: StableRecordIdentifier, options?: Dict<unknown>): Dict<unknown> {
126
+ // called by something V1
127
+ if (!isStableIdentifier(identifier)) {
128
+ options = identifier;
129
+ identifier = this.#identifier;
130
+ }
131
+ let recordData = this.#recordData;
132
+
133
+ // TODO deprecate return value
134
+ if (this.#isDeprecated(recordData)) {
135
+ recordData.clientDidCreate();
136
+ // if a V2 is calling a V1 we need to call both methods
137
+ return recordData._initRecordCreateOptions(options);
138
+ } else {
139
+ return recordData.clientDidCreate(identifier, options);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Pass options to the cache that were supplied to a new record
145
+ * instantiated on the client.
146
+ *
147
+ * DEPRECATED: options are now passed via `clientDidCreate`
148
+ *
149
+ * @method clientDidCreate
150
+ * @public
151
+ * @deprecated
152
+ * @param options
153
+ */
154
+ _initRecordCreateOptions(options?: Dict<unknown>) {
155
+ let recordData = this.#recordData;
156
+
157
+ if (this.#isDeprecated(recordData)) {
158
+ return recordData._initRecordCreateOptions(options);
159
+ }
160
+ }
161
+
162
+ /**
163
+ * [LIFECYCLE] Signals to the cache that a resource
164
+ * will be part of a save transaction.
165
+ *
166
+ * @method willCommit
167
+ * @public
168
+ * @param identifier
169
+ */
170
+ willCommit(identifier: StableRecordIdentifier): void {
171
+ this.#recordData.willCommit(identifier || this.#identifier);
172
+ }
173
+
174
+ /**
175
+ * [LIFECYCLE] Signals to the cache that a resource
176
+ * was successfully updated as part of a save transaction.
177
+ *
178
+ * @method didCommit
179
+ * @public
180
+ * @param identifier
181
+ * @param data
182
+ */
183
+ didCommit(identifier: StableRecordIdentifier, data: JsonApiResource | null): void {
184
+ // called by something V1
185
+ if (!isStableIdentifier(identifier)) {
186
+ data = identifier;
187
+ identifier = this.#identifier;
188
+ }
189
+ let recordData = this.#recordData;
190
+ this.#isDeprecated(recordData) ? recordData.didCommit(data) : recordData.didCommit(identifier, data);
191
+ }
192
+
193
+ /**
194
+ * [LIFECYCLE] Signals to the cache that a resource
195
+ * was update via a save transaction failed.
196
+ *
197
+ * @method commitWasRejected
198
+ * @public
199
+ * @param identifier
200
+ * @param errors
201
+ */
202
+ commitWasRejected(identifier: StableRecordIdentifier, errors?: JsonApiValidationError[]) {
203
+ this.#recordData.commitWasRejected(identifier || this.#identifier, errors);
204
+ }
205
+
206
+ /**
207
+ * [LIFECYCLE] Signals to the cache that all data for a resource
208
+ * should be cleared.
209
+ *
210
+ * @method unloadRecord
211
+ * @public
212
+ * @param identifier
213
+ */
214
+ unloadRecord(identifier: StableRecordIdentifier): void {
215
+ const recordData = this.#recordData;
216
+ if (this.#isDeprecated(recordData)) {
217
+ recordData.unloadRecord();
218
+ } else {
219
+ recordData.unloadRecord(identifier || this.#identifier);
220
+ }
221
+ }
222
+
223
+ // Attrs
224
+ // =====
225
+
226
+ /**
227
+ * Retrieve the data for an attribute from the cache
228
+ *
229
+ * @method getAttr
230
+ * @public
231
+ * @param identifier
232
+ * @param propertyName
233
+ * @returns {unknown}
234
+ */
235
+ getAttr(identifier: StableRecordIdentifier, propertyName: string): unknown {
236
+ // called by something V1
237
+ if (!isStableIdentifier(identifier)) {
238
+ propertyName = identifier;
239
+ identifier = this.#identifier;
240
+ }
241
+ let recordData = this.#recordData;
242
+ return this.#isDeprecated(recordData)
243
+ ? recordData.getAttr(propertyName)
244
+ : recordData.getAttr(identifier, propertyName);
245
+ }
246
+
247
+ /**
248
+ * Mutate the data for an attribute in the cache
249
+ *
250
+ * @method setAttr
251
+ * @public
252
+ * @param identifier
253
+ * @param propertyName
254
+ * @param value
255
+ */
256
+ setAttr(identifier: StableRecordIdentifier, propertyName: string, value: unknown): void {
257
+ let recordData = this.#recordData;
258
+
259
+ this.#isDeprecated(recordData)
260
+ ? recordData.setDirtyAttribute(propertyName, value)
261
+ : recordData.setAttr(identifier, propertyName, value);
262
+ }
263
+
264
+ /**
265
+ * Mutate the data for an attribute in the cache
266
+ *
267
+ * DEPRECATED use setAttr
268
+ *
269
+ * @method setDirtyAttribute
270
+ * @public
271
+ * @deprecated
272
+ * @param identifier
273
+ * @param propertyName
274
+ * @param value
275
+ */
276
+ setDirtyAttribute(propertyName: string, value: unknown): void {
277
+ let recordData = this.#recordData;
278
+
279
+ this.#isDeprecated(recordData)
280
+ ? recordData.setDirtyAttribute(propertyName, value)
281
+ : recordData.setAttr(this.#identifier, propertyName, value);
282
+ }
283
+
284
+ /**
285
+ * Query the cache for the changed attributes of a resource.
286
+ *
287
+ * DEPRECATED use changedAttrs
288
+ *
289
+ * @method changedAttributes
290
+ * @public
291
+ * @deprecated
292
+ * @param identifier
293
+ * @returns
294
+ */
295
+ changedAttributes(): ChangedAttributesHash {
296
+ const recordData = this.#recordData;
297
+ if (this.#isDeprecated(recordData)) {
298
+ return recordData.changedAttributes();
299
+ }
300
+ return recordData.changedAttrs(this.#identifier);
301
+ }
302
+
303
+ /**
304
+ * Query the cache for the changed attributes of a resource.
305
+ *
306
+ * @method changedAttrs
307
+ * @public
308
+ * @deprecated
309
+ * @param identifier
310
+ * @returns
311
+ */
312
+ changedAttrs(identifier: StableRecordIdentifier): ChangedAttributesHash {
313
+ const recordData = this.#recordData;
314
+ if (this.#isDeprecated(recordData)) {
315
+ return recordData.changedAttributes();
316
+ }
317
+ return recordData.changedAttrs(identifier);
318
+ }
319
+
320
+ /**
321
+ * Query the cache for whether any mutated attributes exist
322
+ *
323
+ * DEPRECATED use hasChangedAttrs
324
+ *
325
+ * @method hasChangedAttributes
326
+ * @public
327
+ * @deprecated
328
+ * @returns
329
+ */
330
+ hasChangedAttributes(): boolean {
331
+ const recordData = this.#recordData;
332
+ return this.#isDeprecated(recordData)
333
+ ? recordData.hasChangedAttributes()
334
+ : recordData.hasChangedAttrs(this.#identifier);
335
+ }
336
+
337
+ /**
338
+ * Query the cache for whether any mutated attributes exist
339
+ *
340
+ * @method hasChangedAttrs
341
+ * @public
342
+ * @param identifier
343
+ * @returns
344
+ */
345
+ hasChangedAttrs(identifier: StableRecordIdentifier): boolean {
346
+ const recordData = this.#recordData;
347
+ return this.#isDeprecated(recordData) ? recordData.hasChangedAttributes() : recordData.hasChangedAttrs(identifier);
348
+ }
349
+
350
+ /**
351
+ * Tell the cache to discard any uncommitted mutations to attributes
352
+ *
353
+ * DEPRECATED use rollbackAttrs
354
+ *
355
+ * @method rollbackAttributes
356
+ * @public
357
+ * @deprecated
358
+ * @returns
359
+ */
360
+ rollbackAttributes() {
361
+ const recordData = this.#recordData;
362
+ return this.#isDeprecated(recordData)
363
+ ? recordData.rollbackAttributes()
364
+ : recordData.rollbackAttrs(this.#identifier);
365
+ }
366
+
367
+ /**
368
+ * Tell the cache to discard any uncommitted mutations to attributes
369
+ *
370
+ * @method rollbackAttrs
371
+ * @public
372
+ * @param identifier
373
+ * @returns the names of attributes that were restored
374
+ */
375
+ rollbackAttrs(identifier: StableRecordIdentifier): string[] {
376
+ const recordData = this.#recordData;
377
+ return this.#isDeprecated(recordData) ? recordData.rollbackAttributes() : recordData.rollbackAttrs(identifier);
378
+ }
379
+
380
+ // Relationships
381
+ // =============
382
+
383
+ // the third arg here is "private". In a world with only V2 it is not necessary
384
+ // but in one in which we must convert a call from V2 -> V1 it is required to do this
385
+ // or else to do nasty schema lookup things
386
+ // @runspired has implemented this concept in relationships spikes and is confident
387
+ // we do not need any signal about whether a relationship is a collection or not at this
388
+ // boundary
389
+ /**
390
+ * Query the cache for the current state of a relationship property
391
+ *
392
+ * @method getRelationship
393
+ * @public
394
+ * @param identifier
395
+ * @param propertyName
396
+ * @returns resource relationship object
397
+ */
398
+ getRelationship(
399
+ identifier: StableRecordIdentifier,
400
+ propertyName: string,
401
+ isCollection = false
402
+ ): SingleResourceRelationship | CollectionResourceRelationship {
403
+ let recordData = this.#recordData;
404
+
405
+ if (this.#isDeprecated(recordData)) {
406
+ let isBelongsTo = !isCollection;
407
+ return isBelongsTo ? recordData.getBelongsTo(propertyName) : recordData.getHasMany(propertyName);
408
+ }
409
+
410
+ return recordData.getRelationship(identifier, propertyName);
411
+ }
412
+
413
+ /**
414
+ * Query the cache for the current state of a belongsTo field
415
+ *
416
+ * DEPRECATED use `getRelationship`
417
+ *
418
+ * @method getBelongsTo
419
+ * @public
420
+ * @deprecated
421
+ * @param propertyName
422
+ * @returns single resource relationship object
423
+ */
424
+ getBelongsTo(propertyName: string): SingleResourceRelationship {
425
+ let recordData = this.#recordData;
426
+
427
+ if (this.#isDeprecated(recordData)) {
428
+ return recordData.getBelongsTo(propertyName);
429
+ } else {
430
+ let identifier = this.#identifier;
431
+ return recordData.getRelationship(identifier, propertyName) as SingleResourceRelationship;
432
+ }
433
+ }
434
+
435
+ /**
436
+ * Query the cache for the current state of a hasMany field
437
+ *
438
+ * DEPRECATED use `getRelationship`
439
+ *
440
+ * @method getHasMany
441
+ * @public
442
+ * @deprecated
443
+ * @param propertyName
444
+ * @returns single resource relationship object
445
+ */
446
+ getHasMany(propertyName: string): CollectionResourceRelationship {
447
+ let recordData = this.#recordData;
448
+
449
+ if (this.#isDeprecated(recordData)) {
450
+ return recordData.getHasMany(propertyName);
451
+ } else {
452
+ let identifier = this.#identifier;
453
+ return recordData.getRelationship(identifier, propertyName) as CollectionResourceRelationship;
454
+ }
455
+ }
456
+
457
+ /**
458
+ * Mutate the current state of a belongsTo relationship
459
+ *
460
+ * @method setBelongsTo
461
+ * @public
462
+ * @param identifier
463
+ * @param propertyName
464
+ * @param value
465
+ */
466
+ setBelongsTo(identifier: StableRecordIdentifier, propertyName: string, value: StableRecordIdentifier | null) {
467
+ const store = this.#store;
468
+ const recordData = this.#recordData;
469
+
470
+ this.#isDeprecated(recordData)
471
+ ? recordData.setDirtyBelongsTo(propertyName, value ? store._instanceCache.getRecordData(value) : null)
472
+ : recordData.setBelongsTo(identifier, propertyName, value);
473
+ }
474
+
475
+ /**
476
+ * Mutate the current state of a belongsTo relationship
477
+ *
478
+ * DEPRECATED use setBelongsTo
479
+ *
480
+ * @method setDirtyBelongsTo
481
+ * @public
482
+ * @deprecated
483
+ * @param propertyName
484
+ * @param value
485
+ */
486
+ setDirtyBelongsTo(propertyName: string, value: NonSingletonRecordDataManager | null) {
487
+ const recordData = this.#recordData;
488
+
489
+ this.#isDeprecated(recordData)
490
+ ? recordData.setDirtyBelongsTo(propertyName, value as unknown as RecordData)
491
+ : recordData.setBelongsTo(this.#identifier, propertyName, value ? value.getResourceIdentifier() : null);
492
+ }
493
+
494
+ /**
495
+ * Mutate the current state of a hasMany relationship by adding values
496
+ * An index may optionally be specified which the cache should use for
497
+ * where in the list to insert the records
498
+ *
499
+ * @method addToHasMany
500
+ * @public
501
+ * @param identifier
502
+ * @param propertyName
503
+ * @param value
504
+ * @param idx
505
+ */
506
+ addToHasMany(
507
+ identifier: StableRecordIdentifier,
508
+ propertyName: string,
509
+ value: StableRecordIdentifier[],
510
+ idx?: number
511
+ ): void {
512
+ // called by something V1
513
+ let isFromV1 = false;
514
+ if (!isStableIdentifier(identifier)) {
515
+ isFromV1 = true;
516
+ idx = value as unknown as number;
517
+ value = propertyName as unknown as StableRecordIdentifier[];
518
+ propertyName = identifier as unknown as string;
519
+ identifier = this.#identifier;
520
+ }
521
+ const cache = this.#store._instanceCache;
522
+ const recordData = this.#recordData;
523
+
524
+ this.#isDeprecated(recordData)
525
+ ? recordData.addToHasMany(
526
+ propertyName,
527
+ isFromV1 ? (value as unknown as RecordData[]) : value.map((v) => cache.getRecordData(v)),
528
+ idx
529
+ )
530
+ : recordData.addToHasMany(
531
+ identifier,
532
+ propertyName,
533
+ isFromV1
534
+ ? (value as unknown as NonSingletonRecordDataManager[]).map((v) => v.getResourceIdentifier())
535
+ : value,
536
+ idx
537
+ );
538
+ }
539
+
540
+ /**
541
+ * Mutate the current state of a hasMany relationship by removing values.
542
+ *
543
+ * @method removeFromHasMany
544
+ * @public
545
+ * @param identifier
546
+ * @param propertyName
547
+ * @param value
548
+ */
549
+ removeFromHasMany(identifier: StableRecordIdentifier, propertyName: string, value: StableRecordIdentifier[]): void {
550
+ let isFromV1 = false;
551
+ if (!isStableIdentifier(identifier)) {
552
+ isFromV1 = true;
553
+ value = propertyName as unknown as StableRecordIdentifier[];
554
+ propertyName = identifier as unknown as string;
555
+ identifier = this.#identifier;
556
+ }
557
+ const cache = this.#store._instanceCache;
558
+ const recordData = this.#recordData;
559
+
560
+ this.#isDeprecated(recordData)
561
+ ? recordData.removeFromHasMany(
562
+ propertyName,
563
+ isFromV1 ? (value as unknown as RecordData[]) : value.map((v) => cache.getRecordData(v))
564
+ )
565
+ : recordData.removeFromHasMany(
566
+ identifier,
567
+ propertyName,
568
+ isFromV1 ? (value as unknown as NonSingletonRecordDataManager[]).map((v) => v.getResourceIdentifier()) : value
569
+ );
570
+ }
571
+
572
+ /**
573
+ * Mutate the current state of a hasMany relationship by replacing it entirely
574
+ *
575
+ * @method setHasMany
576
+ * @public
577
+ * @param identifier
578
+ * @param propertyName
579
+ * @param value
580
+ */
581
+ setHasMany(identifier: StableRecordIdentifier, propertyName: string, value: StableRecordIdentifier[]): void {
582
+ const cache = this.#store._instanceCache;
583
+ const recordData = this.#recordData;
584
+
585
+ this.#isDeprecated(recordData)
586
+ ? recordData.setDirtyHasMany(
587
+ propertyName,
588
+ value.map((identifier) => cache.getRecordData(identifier))
589
+ )
590
+ : recordData.setHasMany(identifier, propertyName, value);
591
+ }
592
+
593
+ /**
594
+ * Mutate the current state of a hasMany relationship by replacing it entirely
595
+ *
596
+ * DEPRECATED use `setHasMany`
597
+ *
598
+ * @method setDirtyHasMany
599
+ * @public
600
+ * @deprecated
601
+ * @param propertyName
602
+ * @param value
603
+ */
604
+ setDirtyHasMany(propertyName: string, value: RecordData[]) {
605
+ let recordData = this.#recordData;
606
+
607
+ this.#isDeprecated(recordData)
608
+ ? recordData.setDirtyHasMany(propertyName, value)
609
+ : recordData.setHasMany(
610
+ this.#identifier,
611
+ propertyName,
612
+ (value as unknown as NonSingletonRecordDataManager[]).map((rd) => rd.getResourceIdentifier())
613
+ );
614
+ }
615
+
616
+ // State
617
+ // =============
618
+
619
+ /**
620
+ * Update the cache state for the given resource to be marked as locally deleted,
621
+ * or remove such a mark.
622
+ *
623
+ * @method setIsDeleted
624
+ * @public
625
+ * @param identifier
626
+ * @param isDeleted
627
+ */
628
+ setIsDeleted(identifier: StableRecordIdentifier, isDeleted: boolean): void {
629
+ if (!isStableIdentifier(identifier)) {
630
+ isDeleted = identifier as boolean;
631
+ identifier = this.#identifier;
632
+ }
633
+ const recordData = this.#recordData;
634
+ this.#isDeprecated(recordData)
635
+ ? recordData.setIsDeleted(isDeleted)
636
+ : recordData.setIsDeleted(identifier, isDeleted);
637
+ }
638
+
639
+ /**
640
+ * Query the cache for any validation errors applicable to the given resource.
641
+ *
642
+ * @method getErrors
643
+ * @public
644
+ * @param identifier
645
+ * @returns
646
+ */
647
+ getErrors(identifier: StableRecordIdentifier): JsonApiValidationError[] {
648
+ return this.#recordData.getErrors(identifier || this.#identifier);
649
+ }
650
+
651
+ /**
652
+ * Query the cache for whether a given resource has any available data
653
+ *
654
+ * @method isEmpty
655
+ * @public
656
+ * @param identifier
657
+ * @returns {boolean}
658
+ */
659
+ isEmpty(identifier: StableRecordIdentifier): boolean {
660
+ const recordData = this.#recordData;
661
+ return this.#isDeprecated(recordData)
662
+ ? recordData.isEmpty?.(identifier || this.#identifier) || false
663
+ : recordData.isEmpty(identifier || this.#identifier);
664
+ }
665
+
666
+ /**
667
+ * Query the cache for whether a given resource was created locally and not
668
+ * yet persisted.
669
+ *
670
+ * @method isNew
671
+ * @public
672
+ * @param identifier
673
+ * @returns {boolean}
674
+ */
675
+ isNew(identifier: StableRecordIdentifier): boolean {
676
+ return this.#recordData.isNew(identifier || this.#identifier);
677
+ }
678
+
679
+ /**
680
+ * Query the cache for whether a given resource is marked as deleted (but not
681
+ * necessarily persisted yet).
682
+ *
683
+ * @method isDeleted
684
+ * @public
685
+ * @param identifier
686
+ * @returns {boolean}
687
+ */
688
+ isDeleted(identifier: StableRecordIdentifier): boolean {
689
+ return this.#recordData.isDeleted(identifier || this.#identifier);
690
+ }
691
+
692
+ /**
693
+ * Query the cache for whether a given resource has been deleted and that deletion
694
+ * has also been persisted.
695
+ *
696
+ * @method isDeletionCommitted
697
+ * @public
698
+ * @param identifier
699
+ * @returns {boolean}
700
+ */
701
+ isDeletionCommitted(identifier: StableRecordIdentifier): boolean {
702
+ return this.#recordData.isDeletionCommitted(identifier || this.#identifier);
703
+ }
704
+ }
705
+
706
+ export class SingletonRecordDataManager implements RecordData {
707
+ version: '2' = '2';
708
+
709
+ #store: Store;
710
+ #recordDatas: Map<StableRecordIdentifier, RecordData>;
711
+
712
+ constructor(store: Store) {
713
+ this.#store = store;
714
+ this.#recordDatas = new Map();
715
+ }
716
+
717
+ _addRecordData(identifier: StableRecordIdentifier, recordData: RecordData) {
718
+ this.#recordDatas.set(identifier, recordData);
719
+ }
720
+
721
+ #recordData(identifier: StableRecordIdentifier): RecordData {
722
+ assert(`No RecordData Yet Exists!`, this.#recordDatas.has(identifier));
723
+ return this.#recordDatas.get(identifier)!;
724
+ }
725
+
726
+ // Cache
727
+ // =====
728
+
729
+ pushData(identifier: StableRecordIdentifier, data: JsonApiResource, hasRecord?: boolean): void | string[] {
730
+ return this.#recordData(identifier).pushData(identifier, data, hasRecord);
731
+ }
732
+
733
+ clientDidCreate(identifier: StableRecordIdentifier, options?: Dict<unknown>): Dict<unknown> {
734
+ return this.#recordData(identifier).clientDidCreate(identifier, options);
735
+ }
736
+
737
+ willCommit(identifier: StableRecordIdentifier): void {
738
+ this.#recordData(identifier).willCommit(identifier);
739
+ }
740
+
741
+ didCommit(identifier: StableRecordIdentifier, data: JsonApiResource | null): void {
742
+ this.#recordData(identifier).didCommit(identifier, data);
743
+ }
744
+
745
+ commitWasRejected(identifier: StableRecordIdentifier, errors?: JsonApiValidationError[]): void {
746
+ this.#recordData(identifier).commitWasRejected(identifier, errors);
747
+ }
748
+
749
+ unloadRecord(identifier: StableRecordIdentifier): void {
750
+ this.#recordData(identifier).unloadRecord(identifier);
751
+ }
752
+
753
+ // Attrs
754
+ // =====
755
+
756
+ getAttr(identifier: StableRecordIdentifier, propertyName: string): unknown {
757
+ return this.#recordData(identifier).getAttr(identifier, propertyName);
758
+ }
759
+
760
+ setAttr(identifier: StableRecordIdentifier, propertyName: string, value: unknown): void {
761
+ this.#recordData(identifier).setAttr(identifier, propertyName, value);
762
+ }
763
+
764
+ changedAttrs(identifier: StableRecordIdentifier): ChangedAttributesHash {
765
+ return this.#recordData(identifier).changedAttrs(identifier);
766
+ }
767
+
768
+ hasChangedAttrs(identifier: StableRecordIdentifier): boolean {
769
+ return this.#recordData(identifier).hasChangedAttrs(identifier);
770
+ }
771
+
772
+ rollbackAttrs(identifier: StableRecordIdentifier): string[] {
773
+ return this.#recordData(identifier).rollbackAttrs(identifier);
774
+ }
775
+
776
+ getRelationship(
777
+ identifier: StableRecordIdentifier,
778
+ propertyName: string
779
+ ): SingleResourceRelationship | CollectionResourceRelationship {
780
+ return this.#recordData(identifier).getRelationship(identifier, propertyName);
781
+ }
782
+
783
+ setBelongsTo(identifier: StableRecordIdentifier, propertyName: string, value: StableRecordIdentifier | null) {
784
+ this.#recordData(identifier).setBelongsTo(identifier, propertyName, value);
785
+ }
786
+
787
+ addToHasMany(
788
+ identifier: StableRecordIdentifier,
789
+ propertyName: string,
790
+ value: StableRecordIdentifier[],
791
+ idx?: number
792
+ ): void {
793
+ this.#recordData(identifier).addToHasMany(identifier, propertyName, value, idx);
794
+ }
795
+
796
+ removeFromHasMany(identifier: StableRecordIdentifier, propertyName: string, value: StableRecordIdentifier[]): void {
797
+ this.#recordData(identifier).removeFromHasMany(identifier, propertyName, value);
798
+ }
799
+
800
+ setHasMany(identifier: StableRecordIdentifier, propertyName: string, value: StableRecordIdentifier[]): void {
801
+ this.#recordData(identifier).setHasMany(identifier, propertyName, value);
802
+ }
803
+
804
+ // State
805
+ // =============
806
+
807
+ setIsDeleted(identifier: StableRecordIdentifier, isDeleted: boolean): void {
808
+ this.#recordData(identifier).setIsDeleted(identifier, isDeleted);
809
+ }
810
+
811
+ getErrors(identifier: StableRecordIdentifier): JsonApiValidationError[] {
812
+ return this.#recordData(identifier).getErrors(identifier);
813
+ }
814
+
815
+ isEmpty(identifier: StableRecordIdentifier): boolean {
816
+ return this.#recordData(identifier).isEmpty(identifier);
817
+ }
818
+
819
+ isNew(identifier: StableRecordIdentifier): boolean {
820
+ return this.#recordData(identifier).isNew(identifier);
821
+ }
822
+
823
+ isDeleted(identifier: StableRecordIdentifier): boolean {
824
+ return this.#recordData(identifier).isDeleted(identifier);
825
+ }
826
+
827
+ isDeletionCommitted(identifier: StableRecordIdentifier): boolean {
828
+ return this.#recordData(identifier).isDeletionCommitted(identifier);
829
+ }
830
+ }