@ember-data/store 4.10.0-alpha.2 → 4.10.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/instance-cache.ts +7 -8
- package/addon/-private/legacy-model-support/shim-model-class.ts +5 -10
- package/addon/-private/managers/record-array-manager.ts +4 -1
- package/addon/-private/managers/record-data-manager.ts +1 -1
- package/addon/-private/record-arrays/identifier-array.ts +57 -12
- package/addon/-private/store-service.ts +15 -7
- package/package.json +7 -7
|
@@ -423,16 +423,21 @@ export class InstanceCache {
|
|
|
423
423
|
}
|
|
424
424
|
}
|
|
425
425
|
|
|
426
|
+
let removeFromRecordArray = true;
|
|
426
427
|
if (recordData) {
|
|
428
|
+
removeFromRecordArray = !recordData.isDeletionCommitted(identifier);
|
|
427
429
|
recordData.unloadRecord(identifier);
|
|
428
430
|
this.__instances.recordData.delete(identifier);
|
|
429
431
|
removeRecordDataFor(identifier);
|
|
430
432
|
} else {
|
|
433
|
+
removeFromRecordArray = false;
|
|
431
434
|
this.disconnect(identifier);
|
|
432
435
|
}
|
|
433
436
|
|
|
434
437
|
this.store._fetchManager.clearEntries(identifier);
|
|
435
|
-
|
|
438
|
+
if (removeFromRecordArray) {
|
|
439
|
+
this.store.recordArrayManager.identifierRemoved(identifier);
|
|
440
|
+
}
|
|
436
441
|
if (LOG_INSTANCE_CACHE) {
|
|
437
442
|
// eslint-disable-next-line no-console
|
|
438
443
|
console.log(`InstanceCache: unloaded RecordData for ${String(identifier)}`);
|
|
@@ -471,12 +476,6 @@ export class InstanceCache {
|
|
|
471
476
|
const isEmpty = _isEmpty(this, identifier);
|
|
472
477
|
const isLoading = _isLoading(this, identifier);
|
|
473
478
|
|
|
474
|
-
if (options.preload) {
|
|
475
|
-
this.store._join(() => {
|
|
476
|
-
preloadData(this.store, identifier, options.preload!);
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
|
|
480
479
|
let promise: Promise<StableRecordIdentifier>;
|
|
481
480
|
if (isEmpty) {
|
|
482
481
|
assertIdentifierHasId(identifier);
|
|
@@ -612,7 +611,7 @@ export function recordDataIsFullyDeleted(cache: InstanceCache, identifier: Stabl
|
|
|
612
611
|
models.
|
|
613
612
|
*/
|
|
614
613
|
type PreloadRelationshipValue = RecordInstance | string;
|
|
615
|
-
function preloadData(store: Store, identifier: StableRecordIdentifier, preload: Dict<unknown>) {
|
|
614
|
+
export function preloadData(store: Store, identifier: StableRecordIdentifier, preload: Dict<unknown>) {
|
|
616
615
|
let jsonPayload: JsonApiResource = {};
|
|
617
616
|
//TODO(Igor) consider the polymorphic case
|
|
618
617
|
const schemas = store.getSchemaDefinitionService();
|
|
@@ -81,16 +81,11 @@ export default class ShimModelClass implements ModelSchema {
|
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
eachTransformedAttribute<T>(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
.getSchemaDefinitionService()
|
|
90
|
-
.relationshipsDefinitionFor({ type: this.modelName });
|
|
91
|
-
Object.keys(relationshipDefs).forEach((key) => {
|
|
92
|
-
if (relationshipDefs[key]!.type) {
|
|
93
|
-
callback.call(binding, key, relationshipDefs[key] as RelationshipSchema);
|
|
84
|
+
eachTransformedAttribute<T>(callback: (this: T | undefined, key: string, type: string) => void, binding?: T) {
|
|
85
|
+
const attrDefs = this.__store.getSchemaDefinitionService().attributesDefinitionFor({ type: this.modelName });
|
|
86
|
+
Object.keys(attrDefs).forEach((key) => {
|
|
87
|
+
if (attrDefs[key]!.type) {
|
|
88
|
+
callback.call(binding, key, attrDefs[key]!.type);
|
|
94
89
|
}
|
|
95
90
|
});
|
|
96
91
|
}
|
|
@@ -357,7 +357,10 @@ function sync(array: IdentifierArray, changes: Map<StableRecordIdentifier, 'add'
|
|
|
357
357
|
// state = array[SOURCE] = [];
|
|
358
358
|
} else {
|
|
359
359
|
removes.forEach((i) => {
|
|
360
|
-
state.
|
|
360
|
+
const index = state.indexOf(i);
|
|
361
|
+
if (index !== -1) {
|
|
362
|
+
state.splice(index, 1);
|
|
363
|
+
}
|
|
361
364
|
});
|
|
362
365
|
}
|
|
363
366
|
}
|
|
@@ -119,7 +119,7 @@ export class NonSingletonRecordDataManager implements RecordData {
|
|
|
119
119
|
// called by something V1
|
|
120
120
|
if (!isStableIdentifier(identifier)) {
|
|
121
121
|
data = identifier as JsonApiResource;
|
|
122
|
-
hasRecord = data as boolean;
|
|
122
|
+
hasRecord = data as unknown as boolean;
|
|
123
123
|
identifier = this.#identifier;
|
|
124
124
|
}
|
|
125
125
|
if (this.#isDeprecated(recordData)) {
|
|
@@ -114,6 +114,33 @@ interface PrivateState {
|
|
|
114
114
|
links: Links | PaginationLinks | null;
|
|
115
115
|
meta: Dict<unknown> | null;
|
|
116
116
|
}
|
|
117
|
+
type ForEachCB = (record: RecordInstance, index: number, context: IdentifierArray) => void;
|
|
118
|
+
function safeForEach(
|
|
119
|
+
instance: IdentifierArray,
|
|
120
|
+
arr: StableRecordIdentifier[],
|
|
121
|
+
store: Store,
|
|
122
|
+
callback: ForEachCB,
|
|
123
|
+
target: unknown
|
|
124
|
+
) {
|
|
125
|
+
if (target === undefined) {
|
|
126
|
+
target = null;
|
|
127
|
+
}
|
|
128
|
+
// clone to prevent mutation
|
|
129
|
+
arr = arr.slice();
|
|
130
|
+
assert('`forEach` expects a function as first argument.', typeof callback === 'function');
|
|
131
|
+
|
|
132
|
+
// because we retrieveLatest above we need not worry if array is mutated during iteration
|
|
133
|
+
// by unloadRecord/rollbackAttributes
|
|
134
|
+
// push/add/removeObject may still be problematic
|
|
135
|
+
// but this is a more traditionally expected forEach bug.
|
|
136
|
+
const length = arr.length; // we need to access length to ensure we are consumed
|
|
137
|
+
|
|
138
|
+
for (let index = 0; index < length; index++) {
|
|
139
|
+
callback.call(target, store._instanceCache.getRecord(arr[index]), index, instance);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return instance;
|
|
143
|
+
}
|
|
117
144
|
|
|
118
145
|
/**
|
|
119
146
|
A record array is an array that contains records of a certain type (or modelName).
|
|
@@ -241,15 +268,25 @@ class IdentifierArray {
|
|
|
241
268
|
let fn = boundFns.get(prop);
|
|
242
269
|
|
|
243
270
|
if (fn === undefined) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
271
|
+
if (prop === 'forEach') {
|
|
272
|
+
fn = function () {
|
|
273
|
+
subscribe(_TAG);
|
|
274
|
+
transaction = true;
|
|
275
|
+
let result = safeForEach(receiver, target, store, arguments[0] as ForEachCB, arguments[1]);
|
|
276
|
+
transaction = false;
|
|
277
|
+
return result;
|
|
278
|
+
};
|
|
279
|
+
} else {
|
|
280
|
+
fn = function () {
|
|
281
|
+
subscribe(_TAG);
|
|
282
|
+
// array functions must run through Reflect to work properly
|
|
283
|
+
// binding via other means will not work.
|
|
284
|
+
transaction = true;
|
|
285
|
+
let result = Reflect.apply(target[prop] as ProxiedMethod, receiver, arguments) as unknown;
|
|
286
|
+
transaction = false;
|
|
287
|
+
return result;
|
|
288
|
+
};
|
|
289
|
+
}
|
|
253
290
|
|
|
254
291
|
boundFns.set(prop, fn);
|
|
255
292
|
}
|
|
@@ -271,7 +308,7 @@ class IdentifierArray {
|
|
|
271
308
|
const args: unknown[] = Array.prototype.slice.call(arguments);
|
|
272
309
|
assert(`Cannot start a new array transaction while a previous transaction is underway`, !transaction);
|
|
273
310
|
transaction = true;
|
|
274
|
-
let result = Reflect.apply(target[prop] as ProxiedMethod, receiver, args)
|
|
311
|
+
let result: unknown = Reflect.apply(target[prop] as ProxiedMethod, receiver, args);
|
|
275
312
|
self[MUTATE]!(prop as string, args, result);
|
|
276
313
|
addToTransaction(_TAG);
|
|
277
314
|
// TODO handle cache updates
|
|
@@ -658,13 +695,21 @@ if (DEPRECATE_ARRAY_LIKE) {
|
|
|
658
695
|
|
|
659
696
|
IdentifierArray.prototype.removeObject = function (obj: RecordInstance) {
|
|
660
697
|
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'removeObject', 'splice');
|
|
661
|
-
this.
|
|
698
|
+
const index = this.indexOf(obj);
|
|
699
|
+
if (index !== -1) {
|
|
700
|
+
this.splice(index, 1);
|
|
701
|
+
}
|
|
662
702
|
return this;
|
|
663
703
|
};
|
|
664
704
|
|
|
665
705
|
IdentifierArray.prototype.removeObjects = function (objs: RecordInstance[]) {
|
|
666
706
|
deprecateArrayLike(this.DEPRECATED_CLASS_NAME, 'removeObjects', 'splice');
|
|
667
|
-
objs.forEach((obj) =>
|
|
707
|
+
objs.forEach((obj) => {
|
|
708
|
+
const index = this.indexOf(obj);
|
|
709
|
+
if (index !== -1) {
|
|
710
|
+
this.splice(index, 1);
|
|
711
|
+
}
|
|
712
|
+
});
|
|
668
713
|
return this;
|
|
669
714
|
};
|
|
670
715
|
|
|
@@ -45,6 +45,7 @@ import { IdentifierCache } from './caches/identifier-cache';
|
|
|
45
45
|
import {
|
|
46
46
|
InstanceCache,
|
|
47
47
|
peekRecordIdentifier,
|
|
48
|
+
preloadData,
|
|
48
49
|
recordDataIsFullyDeleted,
|
|
49
50
|
recordIdentifierFor,
|
|
50
51
|
setRecordIdentifier,
|
|
@@ -482,6 +483,7 @@ class Store extends Service {
|
|
|
482
483
|
@return {subclass of Model | ShimModelClass}
|
|
483
484
|
*/
|
|
484
485
|
// TODO @deprecate in favor of schema APIs, requires adapter/serializer overhaul or replacement
|
|
486
|
+
declare _forceShim: boolean;
|
|
485
487
|
modelFor(modelName: string): ShimModelClass | DSModelClass {
|
|
486
488
|
if (DEBUG) {
|
|
487
489
|
assertDestroyedStoreOnly(this, 'modelFor');
|
|
@@ -497,7 +499,7 @@ class Store extends Service {
|
|
|
497
499
|
|
|
498
500
|
// for factorFor factory/class split
|
|
499
501
|
let klass = maybeFactory && maybeFactory.class ? maybeFactory.class : maybeFactory;
|
|
500
|
-
if (!klass || !klass.isModel) {
|
|
502
|
+
if (!klass || !klass.isModel || this._forceShim) {
|
|
501
503
|
assert(
|
|
502
504
|
`No model was found for '${modelName}' and no schema handles the type`,
|
|
503
505
|
this.getSchemaDefinitionService().doesTypeExist(modelName)
|
|
@@ -1127,6 +1129,12 @@ class Store extends Service {
|
|
|
1127
1129
|
let promise;
|
|
1128
1130
|
options = options || {};
|
|
1129
1131
|
|
|
1132
|
+
if (options.preload) {
|
|
1133
|
+
this._join(() => {
|
|
1134
|
+
preloadData(this, identifier, options!.preload!);
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1130
1138
|
// if not loaded start loading
|
|
1131
1139
|
if (!this._instanceCache.recordIsLoaded(identifier)) {
|
|
1132
1140
|
promise = this._instanceCache._fetchDataIfNeededForIdentifier(identifier, options);
|
|
@@ -1134,6 +1142,7 @@ class Store extends Service {
|
|
|
1134
1142
|
// Refetch if the reload option is passed
|
|
1135
1143
|
} else if (options.reload) {
|
|
1136
1144
|
assertIdentifierHasId(identifier);
|
|
1145
|
+
|
|
1137
1146
|
promise = this._fetchManager.scheduleFetch(identifier, options);
|
|
1138
1147
|
} else {
|
|
1139
1148
|
let snapshot: Snapshot | null = null;
|
|
@@ -2310,8 +2319,8 @@ class Store extends Service {
|
|
|
2310
2319
|
|
|
2311
2320
|
const saveOptions = Object.assign({ [SaveOp]: operation }, options);
|
|
2312
2321
|
let fetchManagerPromise = this._fetchManager.scheduleSave(identifier, saveOptions);
|
|
2313
|
-
return fetchManagerPromise
|
|
2314
|
-
(payload) => {
|
|
2322
|
+
return fetchManagerPromise
|
|
2323
|
+
.then((payload) => {
|
|
2315
2324
|
if (LOG_PAYLOADS) {
|
|
2316
2325
|
try {
|
|
2317
2326
|
let data = payload ? JSON.parse(JSON.stringify(payload)) : payload;
|
|
@@ -2366,8 +2375,8 @@ class Store extends Service {
|
|
|
2366
2375
|
}
|
|
2367
2376
|
});
|
|
2368
2377
|
return record;
|
|
2369
|
-
}
|
|
2370
|
-
(e) => {
|
|
2378
|
+
})
|
|
2379
|
+
.catch((e) => {
|
|
2371
2380
|
let err = e;
|
|
2372
2381
|
if (!e) {
|
|
2373
2382
|
err = new Error(`Unknown Error Occurred During Request`);
|
|
@@ -2376,8 +2385,7 @@ class Store extends Service {
|
|
|
2376
2385
|
}
|
|
2377
2386
|
adapterDidInvalidate(this, identifier, err);
|
|
2378
2387
|
throw err;
|
|
2379
|
-
}
|
|
2380
|
-
);
|
|
2388
|
+
});
|
|
2381
2389
|
}
|
|
2382
2390
|
|
|
2383
2391
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ember-data/store",
|
|
3
|
-
"version": "4.10.0-alpha.
|
|
3
|
+
"version": "4.10.0-alpha.4",
|
|
4
4
|
"description": "The core of EmberData. Provides the Store service which coordinates the cache with the network and presentation layers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"author": "",
|
|
15
15
|
"directories": {},
|
|
16
16
|
"peerDependencies": {
|
|
17
|
-
"@ember-data/model": "4.10.0-alpha.
|
|
18
|
-
"@ember-data/record-data": "4.10.0-alpha.
|
|
19
|
-
"@ember-data/tracking": "4.10.0-alpha.
|
|
17
|
+
"@ember-data/model": "4.10.0-alpha.4",
|
|
18
|
+
"@ember-data/record-data": "4.10.0-alpha.4",
|
|
19
|
+
"@ember-data/tracking": "4.10.0-alpha.4",
|
|
20
20
|
"@ember/string": "^3.0.0",
|
|
21
21
|
"@glimmer/tracking": "^1.1.2"
|
|
22
22
|
},
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@ember-data/canary-features": "4.10.0-alpha.
|
|
41
|
-
"@ember-data/private-build-infra": "4.10.0-alpha.
|
|
40
|
+
"@ember-data/canary-features": "4.10.0-alpha.4",
|
|
41
|
+
"@ember-data/private-build-infra": "4.10.0-alpha.4",
|
|
42
42
|
"@embroider/macros": "^1.10.0",
|
|
43
43
|
"ember-auto-import": "^2.5.0",
|
|
44
44
|
"ember-cached-decorator-polyfill": "^1.0.1",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"volta": {
|
|
58
58
|
"extends": "../../package.json"
|
|
59
59
|
},
|
|
60
|
-
"packageManager": "pnpm@7.
|
|
60
|
+
"packageManager": "pnpm@7.18.0"
|
|
61
61
|
}
|