@ember-data/store 4.4.0 → 4.5.0-alpha.2
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/system/core-store.ts +136 -147
- package/addon/-private/system/ds-model-store.ts +1 -10
- package/addon/-private/system/fetch-manager.ts +48 -21
- package/addon/-private/system/model/internal-model.ts +263 -192
- package/addon/-private/system/model/states.js +5 -41
- package/addon/-private/system/{promise-proxies.js → promise-proxies.ts} +31 -21
- package/addon/-private/system/promise-proxy-base.js +7 -0
- package/addon/-private/system/{record-array-manager.js → record-array-manager.ts} +87 -60
- package/addon/-private/system/record-arrays/adapter-populated-record-array.ts +129 -0
- package/addon/-private/system/record-arrays/{record-array.js → record-array.ts} +96 -75
- package/addon/-private/system/record-data-for.ts +2 -0
- package/addon/-private/system/references/belongs-to.ts +3 -2
- package/addon/-private/system/references/has-many.ts +4 -2
- package/addon/-private/system/schema-definition-service.ts +2 -2
- package/addon/-private/system/snapshot-record-array.ts +12 -11
- package/addon/-private/system/snapshot.ts +24 -7
- package/addon/-private/system/store/common.js +24 -1
- package/addon/-private/system/store/finders.js +53 -5
- package/addon/-private/system/store/internal-model-factory.ts +8 -7
- package/addon/-private/system/store/record-data-store-wrapper.ts +7 -2
- package/addon/-private/system/store/serializer-response.ts +85 -0
- package/addon/-private/ts-interfaces/ds-model.ts +15 -7
- package/addon/-private/ts-interfaces/ember-data-json-api.ts +3 -0
- package/addon/-private/ts-interfaces/minimum-adapter-interface.ts +19 -20
- package/addon/-private/ts-interfaces/minimum-serializer-interface.ts +27 -6
- package/addon/-private/ts-interfaces/record-data.ts +4 -1
- package/addon/-private/ts-interfaces/record-instance.ts +3 -1
- package/addon/-private/ts-interfaces/store.ts +1 -0
- package/addon/-private/utils/promise-record.ts +3 -3
- package/index.js +3 -0
- package/package.json +7 -6
- package/addon/-private/system/record-arrays/adapter-populated-record-array.js +0 -95
- package/addon/-private/system/store/serializer-response.js +0 -71
|
@@ -7,9 +7,8 @@ import { DEBUG } from '@glimmer/env';
|
|
|
7
7
|
import type DSModelClass from '@ember-data/model';
|
|
8
8
|
|
|
9
9
|
import type { DSModel } from '../ts-interfaces/ds-model';
|
|
10
|
-
import type {
|
|
10
|
+
import type { StableRecordIdentifier } from '../ts-interfaces/identifier';
|
|
11
11
|
import type { RecordDataRecordWrapper } from '../ts-interfaces/record-data-record-wrapper';
|
|
12
|
-
import type { RelationshipsSchema } from '../ts-interfaces/record-data-schemas';
|
|
13
12
|
import type { SchemaDefinitionService } from '../ts-interfaces/schema-definition-service';
|
|
14
13
|
import CoreStore from './core-store';
|
|
15
14
|
import type ShimModelClass from './model/shim-model-class';
|
|
@@ -108,14 +107,6 @@ class Store extends CoreStore {
|
|
|
108
107
|
return this._relationshipsDefinitionFor({ type: modelName })[key];
|
|
109
108
|
}
|
|
110
109
|
|
|
111
|
-
_attributesDefinitionFor(identifier: RecordIdentifier | { type: string }) {
|
|
112
|
-
return this.getSchemaDefinitionService().attributesDefinitionFor(identifier);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
_relationshipsDefinitionFor(identifier: RecordIdentifier | { type: string }): RelationshipsSchema {
|
|
116
|
-
return this.getSchemaDefinitionService().relationshipsDefinitionFor(identifier);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
110
|
getSchemaDefinitionService(): SchemaDefinitionService {
|
|
120
111
|
if (!this._schemaDefinitionService) {
|
|
121
112
|
this._schemaDefinitionService = new DSModelSchemaDefinitionService(this);
|
|
@@ -2,19 +2,24 @@
|
|
|
2
2
|
* @module @ember-data/store
|
|
3
3
|
*/
|
|
4
4
|
import { A } from '@ember/array';
|
|
5
|
-
import { assert, warn } from '@ember/debug';
|
|
5
|
+
import { assert, deprecate, warn } from '@ember/debug';
|
|
6
6
|
import { _backburner as emberBackburner } from '@ember/runloop';
|
|
7
7
|
import { DEBUG } from '@glimmer/env';
|
|
8
8
|
|
|
9
|
-
import { default as RSVP,
|
|
9
|
+
import { default as RSVP, resolve } from 'rsvp';
|
|
10
|
+
|
|
11
|
+
import { DEPRECATE_RSVP_PROMISE } from '@ember-data/private-build-infra/deprecations';
|
|
10
12
|
|
|
11
13
|
import type { CollectionResourceDocument, SingleResourceDocument } from '../ts-interfaces/ember-data-json-api';
|
|
12
14
|
import type { FindRecordQuery, Request, SaveRecordMutation } from '../ts-interfaces/fetch-manager';
|
|
13
15
|
import type { ExistingRecordIdentifier, RecordIdentifier, StableRecordIdentifier } from '../ts-interfaces/identifier';
|
|
16
|
+
import type { MinimumSerializerInterface } from '../ts-interfaces/minimum-serializer-interface';
|
|
17
|
+
import { FindOptions } from '../ts-interfaces/store';
|
|
14
18
|
import type { Dict } from '../ts-interfaces/utils';
|
|
15
19
|
import coerceId from './coerce-id';
|
|
16
20
|
import type CoreStore from './core-store';
|
|
17
21
|
import { errorsArrayToHash } from './errors-utils';
|
|
22
|
+
import ShimModelClass from './model/shim-model-class';
|
|
18
23
|
import RequestCache, { RequestPromise } from './request-cache';
|
|
19
24
|
import type { PrivateSnapshot } from './snapshot';
|
|
20
25
|
import Snapshot from './snapshot';
|
|
@@ -30,8 +35,15 @@ function payloadIsNotBlank(adapterPayload): boolean {
|
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
type AdapterErrors = Error & { errors?: string[]; isAdapterError?: true };
|
|
39
|
+
type SerializerWithParseErrors = MinimumSerializerInterface & {
|
|
40
|
+
extractErrors?(store: CoreStore, modelClass: ShimModelClass, error: AdapterErrors, recordId: string | null): any;
|
|
41
|
+
};
|
|
42
|
+
|
|
33
43
|
export const SaveOp: unique symbol = Symbol('SaveOp');
|
|
34
44
|
|
|
45
|
+
export type FetchMutationOptions = FindOptions & { [SaveOp]: 'createRecord' | 'deleteRecord' | 'updateRecord' };
|
|
46
|
+
|
|
35
47
|
interface PendingFetchItem {
|
|
36
48
|
identifier: ExistingRecordIdentifier;
|
|
37
49
|
queryRequest: Request;
|
|
@@ -44,7 +56,7 @@ interface PendingSaveItem {
|
|
|
44
56
|
resolver: RSVP.Deferred<any>;
|
|
45
57
|
snapshot: Snapshot;
|
|
46
58
|
identifier: RecordIdentifier;
|
|
47
|
-
options:
|
|
59
|
+
options: FetchMutationOptions;
|
|
48
60
|
queryRequest: Request;
|
|
49
61
|
}
|
|
50
62
|
|
|
@@ -78,7 +90,7 @@ export default class FetchManager {
|
|
|
78
90
|
|
|
79
91
|
@internal
|
|
80
92
|
*/
|
|
81
|
-
scheduleSave(identifier: RecordIdentifier, options:
|
|
93
|
+
scheduleSave(identifier: RecordIdentifier, options: FetchMutationOptions): Promise<null | SingleResourceDocument> {
|
|
82
94
|
let promiseLabel = 'DS: Model#save ' + this;
|
|
83
95
|
let resolver = RSVP.defer<null | SingleResourceDocument>(promiseLabel);
|
|
84
96
|
let query: SaveRecordMutation = {
|
|
@@ -125,8 +137,8 @@ export default class FetchManager {
|
|
|
125
137
|
typeof adapter[operation] === 'function'
|
|
126
138
|
);
|
|
127
139
|
|
|
128
|
-
let promise =
|
|
129
|
-
let serializer = store.serializerFor(modelName);
|
|
140
|
+
let promise = resolve().then(() => adapter[operation](store, modelClass, snapshot));
|
|
141
|
+
let serializer: SerializerWithParseErrors | null = store.serializerFor(modelName);
|
|
130
142
|
let label = `DS: Extract and notify about ${operation} completion of ${internalModel}`;
|
|
131
143
|
|
|
132
144
|
assert(
|
|
@@ -134,11 +146,26 @@ export default class FetchManager {
|
|
|
134
146
|
promise !== undefined
|
|
135
147
|
);
|
|
136
148
|
|
|
137
|
-
promise = guardDestroyedStore(promise, store, label)
|
|
138
|
-
promise = _guard(promise, _bind(_objectIsAlive, internalModel));
|
|
139
|
-
|
|
140
|
-
promise = promise.then(
|
|
149
|
+
promise = _guard(guardDestroyedStore(promise, store, label), _bind(_objectIsAlive, internalModel)).then(
|
|
141
150
|
(adapterPayload) => {
|
|
151
|
+
if (!_objectIsAlive(internalModel)) {
|
|
152
|
+
if (DEPRECATE_RSVP_PROMISE) {
|
|
153
|
+
deprecate(
|
|
154
|
+
`A Promise while saving ${modelName} did not resolve by the time your model was destroyed. This will error in a future release.`,
|
|
155
|
+
false,
|
|
156
|
+
{
|
|
157
|
+
id: 'ember-data:rsvp-unresolved-async',
|
|
158
|
+
until: '5.0',
|
|
159
|
+
for: '@ember-data/store',
|
|
160
|
+
since: {
|
|
161
|
+
available: '4.5',
|
|
162
|
+
enabled: '4.5',
|
|
163
|
+
},
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
142
169
|
if (adapterPayload) {
|
|
143
170
|
return normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation);
|
|
144
171
|
}
|
|
@@ -147,7 +174,8 @@ export default class FetchManager {
|
|
|
147
174
|
if (error && error.isAdapterError === true && error.code === 'InvalidError') {
|
|
148
175
|
let parsedErrors = error.errors;
|
|
149
176
|
|
|
150
|
-
|
|
177
|
+
// TODO deprecate extractErrors being called and/or make it part of the public interface
|
|
178
|
+
if (serializer && typeof serializer.extractErrors === 'function') {
|
|
151
179
|
parsedErrors = serializer.extractErrors(store, modelClass, error, snapshot.id);
|
|
152
180
|
} else {
|
|
153
181
|
parsedErrors = errorsArrayToHash(error.errors);
|
|
@@ -179,7 +207,7 @@ export default class FetchManager {
|
|
|
179
207
|
}
|
|
180
208
|
}
|
|
181
209
|
|
|
182
|
-
scheduleFetch(identifier: ExistingRecordIdentifier, options: any, shouldTrace: boolean):
|
|
210
|
+
scheduleFetch(identifier: ExistingRecordIdentifier, options: any, shouldTrace: boolean): Promise<any> {
|
|
183
211
|
// TODO Probably the store should pass in the query object
|
|
184
212
|
|
|
185
213
|
let query: FindRecordQuery = {
|
|
@@ -262,17 +290,16 @@ export default class FetchManager {
|
|
|
262
290
|
|
|
263
291
|
let snapshot = new Snapshot(fetchItem.options, identifier, this._store);
|
|
264
292
|
let klass = this._store.modelFor(identifier.type);
|
|
265
|
-
|
|
266
|
-
let promise = Promise.resolve().then(() => {
|
|
267
|
-
return adapter.findRecord(this._store, klass, identifier.id, snapshot);
|
|
268
|
-
});
|
|
269
|
-
|
|
270
293
|
let id = identifier.id;
|
|
271
|
-
|
|
272
294
|
let label = `DS: Handle Adapter#findRecord of '${modelName}' with id: '${id}'`;
|
|
273
295
|
|
|
274
|
-
promise = guardDestroyedStore(
|
|
275
|
-
|
|
296
|
+
let promise = guardDestroyedStore(
|
|
297
|
+
resolve().then(() => {
|
|
298
|
+
return adapter.findRecord(this._store, klass, identifier.id, snapshot);
|
|
299
|
+
}),
|
|
300
|
+
this._store,
|
|
301
|
+
label
|
|
302
|
+
).then(
|
|
276
303
|
(adapterPayload) => {
|
|
277
304
|
assert(
|
|
278
305
|
`You made a 'findRecord' request for a '${modelName}' with id '${id}', but the adapter's response did not have any data`,
|
|
@@ -487,7 +514,7 @@ export default class FetchManager {
|
|
|
487
514
|
|
|
488
515
|
let groups: Snapshot[][];
|
|
489
516
|
if (adapter.groupRecordsForFindMany) {
|
|
490
|
-
groups = adapter.groupRecordsForFindMany(this, snapshots);
|
|
517
|
+
groups = adapter.groupRecordsForFindMany(this._store, snapshots);
|
|
491
518
|
} else {
|
|
492
519
|
groups = [snapshots];
|
|
493
520
|
}
|