@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
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { deprecate } from '@ember/debug';
|
|
1
2
|
import { get } from '@ember/object';
|
|
2
3
|
import { DEBUG } from '@glimmer/env';
|
|
3
4
|
|
|
4
5
|
import { resolve } from 'rsvp';
|
|
5
6
|
|
|
7
|
+
import { DEPRECATE_RSVP_PROMISE } from '@ember-data/private-build-infra/deprecations';
|
|
8
|
+
|
|
6
9
|
/**
|
|
7
10
|
@module @ember-data/store
|
|
8
11
|
*/
|
|
@@ -32,7 +35,27 @@ export function guardDestroyedStore(promise, store, label) {
|
|
|
32
35
|
if (DEBUG) {
|
|
33
36
|
token = store._trackAsyncRequestStart(label);
|
|
34
37
|
}
|
|
35
|
-
let wrapperPromise = resolve(promise, label).then((
|
|
38
|
+
let wrapperPromise = resolve(promise, label).then((_v) => {
|
|
39
|
+
if (!_objectIsAlive(store)) {
|
|
40
|
+
if (DEPRECATE_RSVP_PROMISE) {
|
|
41
|
+
deprecate(
|
|
42
|
+
`A Promise did not resolve by the time the store was destroyed. This will error in a future release.`,
|
|
43
|
+
false,
|
|
44
|
+
{
|
|
45
|
+
id: 'ember-data:rsvp-unresolved-async',
|
|
46
|
+
until: '5.0',
|
|
47
|
+
for: '@ember-data/store',
|
|
48
|
+
since: {
|
|
49
|
+
available: '4.5',
|
|
50
|
+
enabled: '4.5',
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return promise;
|
|
58
|
+
});
|
|
36
59
|
|
|
37
60
|
return _guard(wrapperPromise, () => {
|
|
38
61
|
if (DEBUG) {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { assert } from '@ember/debug';
|
|
1
|
+
import { assert, deprecate } from '@ember/debug';
|
|
2
2
|
import { DEBUG } from '@glimmer/env';
|
|
3
3
|
|
|
4
4
|
import { Promise } from 'rsvp';
|
|
5
5
|
|
|
6
|
+
import { DEPRECATE_RSVP_PROMISE } from '@ember-data/private-build-infra/deprecations';
|
|
7
|
+
|
|
6
8
|
import { _bind, _guard, _objectIsAlive, guardDestroyedStore } from './common';
|
|
7
9
|
import { normalizeResponseHelper } from './serializer-response';
|
|
8
10
|
|
|
@@ -212,10 +214,26 @@ export function _findHasMany(adapter, store, internalModel, link, relationship,
|
|
|
212
214
|
let label = `DS: Handle Adapter#findHasMany of '${internalModel.modelName}' : '${relationship.type}'`;
|
|
213
215
|
|
|
214
216
|
promise = guardDestroyedStore(promise, store, label);
|
|
215
|
-
promise =
|
|
216
|
-
|
|
217
|
-
return promise.then(
|
|
217
|
+
promise = promise.then(
|
|
218
218
|
(adapterPayload) => {
|
|
219
|
+
if (!_objectIsAlive(internalModel)) {
|
|
220
|
+
if (DEPRECATE_RSVP_PROMISE) {
|
|
221
|
+
deprecate(
|
|
222
|
+
`A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`,
|
|
223
|
+
false,
|
|
224
|
+
{
|
|
225
|
+
id: 'ember-data:rsvp-unresolved-async',
|
|
226
|
+
until: '5.0',
|
|
227
|
+
for: '@ember-data/store',
|
|
228
|
+
since: {
|
|
229
|
+
available: '4.5',
|
|
230
|
+
enabled: '4.5',
|
|
231
|
+
},
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
219
237
|
assert(
|
|
220
238
|
`You made a 'findHasMany' request for a ${internalModel.modelName}'s '${relationship.key}' relationship, using link '${link}' , but the adapter's response did not have any data`,
|
|
221
239
|
payloadIsNotBlank(adapterPayload)
|
|
@@ -236,6 +254,12 @@ export function _findHasMany(adapter, store, internalModel, link, relationship,
|
|
|
236
254
|
null,
|
|
237
255
|
`DS: Extract payload of '${internalModel.modelName}' : hasMany '${relationship.type}'`
|
|
238
256
|
);
|
|
257
|
+
|
|
258
|
+
if (DEPRECATE_RSVP_PROMISE) {
|
|
259
|
+
promise = _guard(promise, _bind(_objectIsAlive, internalModel));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return promise;
|
|
239
263
|
}
|
|
240
264
|
|
|
241
265
|
export function _findBelongsTo(adapter, store, internalModel, link, relationship, options) {
|
|
@@ -249,8 +273,26 @@ export function _findBelongsTo(adapter, store, internalModel, link, relationship
|
|
|
249
273
|
promise = guardDestroyedStore(promise, store, label);
|
|
250
274
|
promise = _guard(promise, _bind(_objectIsAlive, internalModel));
|
|
251
275
|
|
|
252
|
-
|
|
276
|
+
promise = promise.then(
|
|
253
277
|
(adapterPayload) => {
|
|
278
|
+
if (!_objectIsAlive(internalModel)) {
|
|
279
|
+
if (DEPRECATE_RSVP_PROMISE) {
|
|
280
|
+
deprecate(
|
|
281
|
+
`A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`,
|
|
282
|
+
false,
|
|
283
|
+
{
|
|
284
|
+
id: 'ember-data:rsvp-unresolved-async',
|
|
285
|
+
until: '5.0',
|
|
286
|
+
for: '@ember-data/store',
|
|
287
|
+
since: {
|
|
288
|
+
available: '4.5',
|
|
289
|
+
enabled: '4.5',
|
|
290
|
+
},
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
254
296
|
let serializer = store.serializerFor(relationship.type);
|
|
255
297
|
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo');
|
|
256
298
|
|
|
@@ -271,6 +313,12 @@ export function _findBelongsTo(adapter, store, internalModel, link, relationship
|
|
|
271
313
|
null,
|
|
272
314
|
`DS: Extract payload of ${internalModel.modelName} : ${relationship.type}`
|
|
273
315
|
);
|
|
316
|
+
|
|
317
|
+
if (DEPRECATE_RSVP_PROMISE) {
|
|
318
|
+
promise = _guard(promise, _bind(_objectIsAlive, internalModel));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return promise;
|
|
274
322
|
}
|
|
275
323
|
|
|
276
324
|
export function _findAll(adapter, store, modelName, options) {
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
ResourceIdentifierObject,
|
|
10
10
|
} from '../../ts-interfaces/ember-data-json-api';
|
|
11
11
|
import type { StableRecordIdentifier } from '../../ts-interfaces/identifier';
|
|
12
|
+
import type { RecordData } from '../../ts-interfaces/record-data';
|
|
12
13
|
import type { RecordInstance } from '../../ts-interfaces/record-instance';
|
|
13
14
|
import constructResource from '../../utils/construct-resource';
|
|
14
15
|
import type CoreStore from '../core-store';
|
|
@@ -20,19 +21,19 @@ import WeakCache from '../weak-cache';
|
|
|
20
21
|
/**
|
|
21
22
|
@module @ember-data/store
|
|
22
23
|
*/
|
|
23
|
-
|
|
24
24
|
const FactoryCache = new WeakCache<CoreStore, InternalModelFactory>(DEBUG ? 'internal-model-factory' : '');
|
|
25
25
|
FactoryCache._generator = (store: CoreStore) => {
|
|
26
26
|
return new InternalModelFactory(store);
|
|
27
27
|
};
|
|
28
28
|
type NewResourceInfo = { type: string; id: string | null };
|
|
29
29
|
|
|
30
|
-
const RecordCache = new WeakCache<RecordInstance, StableRecordIdentifier>(DEBUG ? 'identifier' : '');
|
|
30
|
+
const RecordCache = new WeakCache<RecordInstance | RecordData, StableRecordIdentifier>(DEBUG ? 'identifier' : '');
|
|
31
31
|
if (DEBUG) {
|
|
32
|
-
RecordCache._expectMsg = (key: RecordInstance) =>
|
|
32
|
+
RecordCache._expectMsg = (key: RecordInstance | RecordData) =>
|
|
33
|
+
`${String(key)} is not a record instantiated by @ember-data/store`;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
export function peekRecordIdentifier(record:
|
|
36
|
+
export function peekRecordIdentifier(record: RecordInstance | RecordData): StableRecordIdentifier | undefined {
|
|
36
37
|
return RecordCache.get(record);
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -60,11 +61,11 @@ export function peekRecordIdentifier(record: any): StableRecordIdentifier | unde
|
|
|
60
61
|
@param {Object} record a record instance previously obstained from the store.
|
|
61
62
|
@returns {StableRecordIdentifier}
|
|
62
63
|
*/
|
|
63
|
-
export function recordIdentifierFor(record: RecordInstance): StableRecordIdentifier {
|
|
64
|
+
export function recordIdentifierFor(record: RecordInstance | RecordData): StableRecordIdentifier {
|
|
64
65
|
return RecordCache.getWithError(record);
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
export function setRecordIdentifier(record: RecordInstance, identifier: StableRecordIdentifier): void {
|
|
68
|
+
export function setRecordIdentifier(record: RecordInstance | RecordData, identifier: StableRecordIdentifier): void {
|
|
68
69
|
if (DEBUG && RecordCache.has(record)) {
|
|
69
70
|
throw new Error(`${record} was already assigned an identifier`);
|
|
70
71
|
}
|
|
@@ -160,7 +161,7 @@ export default class InternalModelFactory {
|
|
|
160
161
|
TODO @runspired consider adding this to make polymorphism even nicer
|
|
161
162
|
if (HAS_RECORD_DATA_PACKAGE) {
|
|
162
163
|
if (identifier.type !== matchedIdentifier.type) {
|
|
163
|
-
const graphFor =
|
|
164
|
+
const graphFor = importSync('@ember-data/record-data/-private').graphFor;
|
|
164
165
|
graphFor(this).registerPolymorphicType(identifier.type, matchedIdentifier.type);
|
|
165
166
|
}
|
|
166
167
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { importSync } from '@embroider/macros';
|
|
2
|
+
|
|
1
3
|
import type { RelationshipDefinition } from '@ember-data/model/-private/system/relationships/relationship-meta';
|
|
2
4
|
import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
|
|
3
5
|
|
|
@@ -10,6 +12,7 @@ import type {
|
|
|
10
12
|
RelationshipsSchema,
|
|
11
13
|
} from '../../ts-interfaces/record-data-schemas';
|
|
12
14
|
import type { RecordDataStoreWrapper as StoreWrapper } from '../../ts-interfaces/record-data-store-wrapper';
|
|
15
|
+
import { RecordInstance } from '../../ts-interfaces/record-instance';
|
|
13
16
|
import constructResource from '../../utils/construct-resource';
|
|
14
17
|
import type CoreStore from '../core-store';
|
|
15
18
|
import { internalModelFactoryFor } from './internal-model-factory';
|
|
@@ -26,7 +29,9 @@ let peekGraph;
|
|
|
26
29
|
if (HAS_RECORD_DATA_PACKAGE) {
|
|
27
30
|
let _peekGraph;
|
|
28
31
|
peekGraph = (wrapper) => {
|
|
29
|
-
_peekGraph =
|
|
32
|
+
_peekGraph =
|
|
33
|
+
_peekGraph ||
|
|
34
|
+
(importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')).peekGraph;
|
|
30
35
|
return _peekGraph(wrapper);
|
|
31
36
|
};
|
|
32
37
|
}
|
|
@@ -220,7 +225,7 @@ export default class RecordDataStoreWrapper implements StoreWrapper {
|
|
|
220
225
|
return false;
|
|
221
226
|
}
|
|
222
227
|
|
|
223
|
-
const record = internalModel._record;
|
|
228
|
+
const record = internalModel._record as RecordInstance;
|
|
224
229
|
return record && !(record.isDestroyed || record.isDestroying);
|
|
225
230
|
}
|
|
226
231
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { assert } from '@ember/debug';
|
|
2
|
+
import { DEBUG } from '@glimmer/env';
|
|
3
|
+
|
|
4
|
+
import { JsonApiDocument } from '../../ts-interfaces/ember-data-json-api';
|
|
5
|
+
import { AdapterPayload } from '../../ts-interfaces/minimum-adapter-interface';
|
|
6
|
+
import { MinimumSerializerInterface, RequestType } from '../../ts-interfaces/minimum-serializer-interface';
|
|
7
|
+
import CoreStore from '../core-store';
|
|
8
|
+
import ShimModelClass from '../model/shim-model-class';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
This is a helper method that validates a JSON API top-level document
|
|
12
|
+
|
|
13
|
+
The format of a document is described here:
|
|
14
|
+
http://jsonapi.org/format/#document-top-level
|
|
15
|
+
|
|
16
|
+
@internal
|
|
17
|
+
*/
|
|
18
|
+
function validateDocumentStructure(doc?: AdapterPayload | JsonApiDocument): asserts doc is JsonApiDocument {
|
|
19
|
+
if (DEBUG) {
|
|
20
|
+
let errors: string[] = [];
|
|
21
|
+
if (!doc || typeof doc !== 'object') {
|
|
22
|
+
errors.push('Top level of a JSON API document must be an object');
|
|
23
|
+
} else {
|
|
24
|
+
if (!('data' in doc) && !('errors' in doc) && !('meta' in doc)) {
|
|
25
|
+
errors.push('One or more of the following keys must be present: "data", "errors", "meta".');
|
|
26
|
+
} else {
|
|
27
|
+
if ('data' in doc && 'errors' in doc) {
|
|
28
|
+
errors.push('Top level keys "errors" and "data" cannot both be present in a JSON API document');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if ('data' in doc) {
|
|
32
|
+
if (!(doc.data === null || Array.isArray(doc.data) || typeof doc.data === 'object')) {
|
|
33
|
+
errors.push('data must be null, an object, or an array');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if ('meta' in doc) {
|
|
37
|
+
if (typeof doc.meta !== 'object') {
|
|
38
|
+
errors.push('meta must be an object');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if ('errors' in doc) {
|
|
42
|
+
if (!Array.isArray(doc.errors)) {
|
|
43
|
+
errors.push('errors must be an array');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if ('links' in doc) {
|
|
47
|
+
if (typeof doc.links !== 'object') {
|
|
48
|
+
errors.push('links must be an object');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if ('jsonapi' in doc) {
|
|
52
|
+
if (typeof doc.jsonapi !== 'object') {
|
|
53
|
+
errors.push('jsonapi must be an object');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if ('included' in doc) {
|
|
57
|
+
if (typeof doc.included !== 'object') {
|
|
58
|
+
errors.push('included must be an array');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
assert(
|
|
64
|
+
`Response must be normalized to a valid JSON API document:\n\t* ${errors.join('\n\t* ')}`,
|
|
65
|
+
errors.length === 0
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function normalizeResponseHelper(
|
|
71
|
+
serializer: MinimumSerializerInterface | null,
|
|
72
|
+
store: CoreStore,
|
|
73
|
+
modelClass: ShimModelClass,
|
|
74
|
+
payload: AdapterPayload,
|
|
75
|
+
id: string | null,
|
|
76
|
+
requestType: RequestType
|
|
77
|
+
): JsonApiDocument {
|
|
78
|
+
let normalizedResponse = serializer
|
|
79
|
+
? serializer.normalizeResponse(store, modelClass, payload, id, requestType)
|
|
80
|
+
: payload;
|
|
81
|
+
|
|
82
|
+
validateDocumentStructure(normalizedResponse);
|
|
83
|
+
|
|
84
|
+
return normalizedResponse;
|
|
85
|
+
}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import EmberObject from '@ember/object';
|
|
1
|
+
import type EmberObject from '@ember/object';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import type { Errors } from '@ember-data/model/-private';
|
|
4
4
|
|
|
5
|
+
import type CoreStore from '../system/core-store';
|
|
6
|
+
import type InternalModel from '../system/model/internal-model';
|
|
5
7
|
import type { JsonApiValidationError } from './record-data-json-api';
|
|
6
|
-
import type { AttributeSchema, RelationshipSchema } from './record-data-schemas';
|
|
7
|
-
import { RecordInstance } from './record-instance';
|
|
8
|
+
import type { AttributeSchema, RelationshipSchema, RelationshipsSchema } from './record-data-schemas';
|
|
8
9
|
|
|
9
10
|
// Placeholder until model.js is typed
|
|
10
|
-
export interface DSModel extends
|
|
11
|
+
export interface DSModel extends EmberObject {
|
|
12
|
+
constructor: DSModelSchema;
|
|
13
|
+
store: CoreStore;
|
|
14
|
+
errors: Errors;
|
|
15
|
+
_internalModel: InternalModel;
|
|
11
16
|
toString(): string;
|
|
12
|
-
save():
|
|
17
|
+
save(): Promise<DSModel>;
|
|
13
18
|
eachRelationship<T>(callback: (this: T, key: string, meta: RelationshipSchema) => void, binding?: T): void;
|
|
14
19
|
eachAttribute<T>(callback: (this: T, key: string, meta: AttributeSchema) => void, binding?: T): void;
|
|
15
20
|
invalidErrorsChanged(errors: JsonApiValidationError[]): void;
|
|
@@ -17,7 +22,7 @@ export interface DSModel extends RecordInstance, EmberObject {
|
|
|
17
22
|
isDeleted: boolean;
|
|
18
23
|
deleteRecord(): void;
|
|
19
24
|
unloadRecord(): void;
|
|
20
|
-
|
|
25
|
+
_notifyProperties(keys: string[]): void;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
// Implemented by both ShimModelClass and DSModel
|
|
@@ -39,4 +44,7 @@ export interface ModelSchema {
|
|
|
39
44
|
// once we can type it.
|
|
40
45
|
export interface DSModelSchema extends ModelSchema {
|
|
41
46
|
isModel: true;
|
|
47
|
+
relationshipsObject: RelationshipsSchema;
|
|
48
|
+
extend(...mixins: unknown[]): DSModelSchema;
|
|
49
|
+
reopenClass(...mixins: unknown[]): void;
|
|
42
50
|
}
|
|
@@ -125,6 +125,9 @@ export interface ExistingResourceObject extends ExistingResourceIdentifierObject
|
|
|
125
125
|
interface Document {
|
|
126
126
|
meta?: Dict<JSONValue>;
|
|
127
127
|
included?: ExistingResourceObject[];
|
|
128
|
+
jsonapi?: Dict<JSONValue>;
|
|
129
|
+
links?: Dict<string | JSONValue>;
|
|
130
|
+
errors?: JSONValue[];
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
export interface EmptyResourceDocument extends Document {
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
// the above eslint rule checks return types. This is an interface
|
|
2
|
-
// and we intend Promise whether it is Native or polyfilled is of
|
|
3
|
-
// no consequence.
|
|
4
|
-
|
|
5
1
|
import type Store from '../system/core-store';
|
|
6
2
|
import type AdapterPopulatedRecordArray from '../system/record-arrays/adapter-populated-record-array';
|
|
7
3
|
import type Snapshot from '../system/snapshot';
|
|
@@ -11,7 +7,12 @@ import type { RelationshipSchema } from './record-data-schemas';
|
|
|
11
7
|
import type { Dict } from './utils';
|
|
12
8
|
|
|
13
9
|
type Group = Snapshot[];
|
|
14
|
-
|
|
10
|
+
// TODO this should probably just alias unknown
|
|
11
|
+
// since in theory a user could pass a blob or a string
|
|
12
|
+
// however those deserialization cases are handled
|
|
13
|
+
// far easier in the adapter itself and are unlikely
|
|
14
|
+
// to be passed to the serializer today.
|
|
15
|
+
export type AdapterPayload = Dict<unknown> | unknown[];
|
|
15
16
|
/**
|
|
16
17
|
* @module @ember-data/adapter
|
|
17
18
|
*/
|
|
@@ -26,7 +27,7 @@ type Group = Snapshot[];
|
|
|
26
27
|
@class MinimumAdapterInterface
|
|
27
28
|
@public
|
|
28
29
|
*/
|
|
29
|
-
interface
|
|
30
|
+
export interface MinimumAdapterInterface {
|
|
30
31
|
/**
|
|
31
32
|
* `adapter.findRecord` takes a request for a resource of a given `type` and `id` combination
|
|
32
33
|
* and should return a `Promise` which fulfills with data for a single resource matching that
|
|
@@ -54,7 +55,7 @@ interface Adapter {
|
|
|
54
55
|
* @param {Snapshot} snapshot
|
|
55
56
|
* @return {Promise} a promise resolving with resource data to feed to the associated serializer
|
|
56
57
|
*/
|
|
57
|
-
findRecord(store: Store, schema: ModelSchema, id: string, snapshot: Snapshot): Promise<
|
|
58
|
+
findRecord(store: Store, schema: ModelSchema, id: string, snapshot: Snapshot): Promise<AdapterPayload>;
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
61
|
* `adapter.findAll` takes a request for resources of a given `type` and should return
|
|
@@ -91,7 +92,7 @@ interface Adapter {
|
|
|
91
92
|
schema: ModelSchema,
|
|
92
93
|
sinceToken: null,
|
|
93
94
|
snapshotRecordArray: SnapshotRecordArray
|
|
94
|
-
): Promise<
|
|
95
|
+
): Promise<AdapterPayload>;
|
|
95
96
|
|
|
96
97
|
/**
|
|
97
98
|
* `adapter.query` takes a request for resources of a given `type` and should return
|
|
@@ -127,10 +128,10 @@ interface Adapter {
|
|
|
127
128
|
query(
|
|
128
129
|
store: Store,
|
|
129
130
|
schema: ModelSchema,
|
|
130
|
-
query: Dict<
|
|
131
|
+
query: Dict<unknown>,
|
|
131
132
|
recordArray: AdapterPopulatedRecordArray,
|
|
132
133
|
options: { adapterOptions?: unknown }
|
|
133
|
-
): Promise<
|
|
134
|
+
): Promise<AdapterPayload>;
|
|
134
135
|
|
|
135
136
|
/**
|
|
136
137
|
* `adapter.queryRecord` takes a request for resource of a given `type` and should return
|
|
@@ -158,9 +159,9 @@ interface Adapter {
|
|
|
158
159
|
queryRecord(
|
|
159
160
|
store: Store,
|
|
160
161
|
schema: ModelSchema,
|
|
161
|
-
query: Dict<
|
|
162
|
+
query: Dict<unknown>,
|
|
162
163
|
options: { adapterOptions?: unknown }
|
|
163
|
-
): Promise<
|
|
164
|
+
): Promise<AdapterPayload>;
|
|
164
165
|
|
|
165
166
|
/**
|
|
166
167
|
* `adapter.createRecord` takes a request to create a resource of a given `type` and should
|
|
@@ -213,7 +214,7 @@ interface Adapter {
|
|
|
213
214
|
* @param {Snapshot} snapshot
|
|
214
215
|
* @return {Promise} a promise resolving with resource data to feed to the associated serializer
|
|
215
216
|
*/
|
|
216
|
-
createRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<
|
|
217
|
+
createRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload>;
|
|
217
218
|
|
|
218
219
|
/**
|
|
219
220
|
* `adapter.updateRecord` takes a request to update a resource of a given `type` and should
|
|
@@ -265,7 +266,7 @@ interface Adapter {
|
|
|
265
266
|
* the type, attributes and relationships of the primary type associated with the request.
|
|
266
267
|
* @param {Snapshot} snapshot
|
|
267
268
|
*/
|
|
268
|
-
updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<
|
|
269
|
+
updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload>;
|
|
269
270
|
|
|
270
271
|
/**
|
|
271
272
|
* `adapter.deleteRecord` takes a request to delete a resource of a given `type` and
|
|
@@ -293,7 +294,7 @@ interface Adapter {
|
|
|
293
294
|
* @param {Snapshot} snapshot A Snapshot containing the record's current data
|
|
294
295
|
* @return
|
|
295
296
|
*/
|
|
296
|
-
deleteRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<
|
|
297
|
+
deleteRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<AdapterPayload>;
|
|
297
298
|
|
|
298
299
|
/**
|
|
299
300
|
* `adapter.findBelongsTo` takes a request to fetch a related resource located at a
|
|
@@ -330,7 +331,7 @@ interface Adapter {
|
|
|
330
331
|
snapshot: Snapshot,
|
|
331
332
|
relatedLink: string,
|
|
332
333
|
relationship: RelationshipSchema
|
|
333
|
-
): Promise<
|
|
334
|
+
): Promise<AdapterPayload>;
|
|
334
335
|
|
|
335
336
|
/**
|
|
336
337
|
* `adapter.findHasMany` takes a request to fetch a related resource collection located
|
|
@@ -368,7 +369,7 @@ interface Adapter {
|
|
|
368
369
|
snapshot: Snapshot,
|
|
369
370
|
relatedLink: string,
|
|
370
371
|
relationship: RelationshipSchema
|
|
371
|
-
): Promise<
|
|
372
|
+
): Promise<AdapterPayload>;
|
|
372
373
|
|
|
373
374
|
/**
|
|
374
375
|
* ⚠️ This Method is only called if `coalesceFindRequests` is `true`. The array passed to it is determined
|
|
@@ -399,7 +400,7 @@ interface Adapter {
|
|
|
399
400
|
* @param {Array<Snapshot>} snapshots An array of snapshots of the available data for the resources to fetch
|
|
400
401
|
* @return {Promise} a promise resolving with resource data to feed to the associated serializer
|
|
401
402
|
*/
|
|
402
|
-
findMany?(store: Store, schema: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<
|
|
403
|
+
findMany?(store: Store, schema: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<AdapterPayload>;
|
|
403
404
|
|
|
404
405
|
/**
|
|
405
406
|
* This method provides the ability to generate an ID to assign to a new record whenever `store.createRecord`
|
|
@@ -581,5 +582,3 @@ interface Adapter {
|
|
|
581
582
|
*/
|
|
582
583
|
destroy?(): void;
|
|
583
584
|
}
|
|
584
|
-
|
|
585
|
-
export default Adapter;
|
|
@@ -4,10 +4,21 @@ import type Store from '../system/core-store';
|
|
|
4
4
|
import type Snapshot from '../system/snapshot';
|
|
5
5
|
import type { ModelSchema } from './ds-model';
|
|
6
6
|
import type { JsonApiDocument, SingleResourceDocument } from './ember-data-json-api';
|
|
7
|
+
import type { AdapterPayload } from './minimum-adapter-interface';
|
|
7
8
|
import type { Dict } from './utils';
|
|
8
9
|
|
|
9
|
-
type OptionsHash = Dict<
|
|
10
|
-
|
|
10
|
+
export type OptionsHash = Dict<unknown>;
|
|
11
|
+
export type RequestType =
|
|
12
|
+
| 'findRecord'
|
|
13
|
+
| 'queryRecord'
|
|
14
|
+
| 'findAll'
|
|
15
|
+
| 'findBelongsTo'
|
|
16
|
+
| 'findHasMany'
|
|
17
|
+
| 'findMany'
|
|
18
|
+
| 'query'
|
|
19
|
+
| 'createRecord'
|
|
20
|
+
| 'deleteRecord'
|
|
21
|
+
| 'updateRecord';
|
|
11
22
|
/**
|
|
12
23
|
@module @ember-data/serializer
|
|
13
24
|
*/
|
|
@@ -22,7 +33,7 @@ type OptionsHash = Dict<any>;
|
|
|
22
33
|
@class MinimumSerializerInterface
|
|
23
34
|
@public
|
|
24
35
|
*/
|
|
25
|
-
interface
|
|
36
|
+
export interface MinimumSerializerInterface {
|
|
26
37
|
/**
|
|
27
38
|
* This method is responsible for normalizing the value resolved from the promise returned
|
|
28
39
|
* by an Adapter request into the format expected by the `Store`.
|
|
@@ -56,7 +67,7 @@ interface Serializer {
|
|
|
56
67
|
normalizeResponse(
|
|
57
68
|
store: Store,
|
|
58
69
|
schema: ModelSchema,
|
|
59
|
-
rawPayload:
|
|
70
|
+
rawPayload: AdapterPayload,
|
|
60
71
|
id: string | null,
|
|
61
72
|
requestType:
|
|
62
73
|
| 'findRecord'
|
|
@@ -231,6 +242,16 @@ interface Serializer {
|
|
|
231
242
|
* @returns {void}
|
|
232
243
|
*/
|
|
233
244
|
pushPayload?(store: Store, rawPayload: JSONObject): void;
|
|
234
|
-
}
|
|
235
245
|
|
|
236
|
-
|
|
246
|
+
/**
|
|
247
|
+
* In some situations the serializer may need to perform cleanup when destroyed,
|
|
248
|
+
* that cleanup can be done in `destroy`.
|
|
249
|
+
*
|
|
250
|
+
* If not implemented, the store does not inform the serializer of destruction.
|
|
251
|
+
*
|
|
252
|
+
* @method destroy [OPTIONAL]
|
|
253
|
+
* @public
|
|
254
|
+
* @optional
|
|
255
|
+
*/
|
|
256
|
+
destroy?(): void;
|
|
257
|
+
}
|
|
@@ -12,7 +12,10 @@ export interface ChangedAttributesHash {
|
|
|
12
12
|
|
|
13
13
|
export interface RecordData {
|
|
14
14
|
getResourceIdentifier(): RecordIdentifier | undefined;
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
pushData(data: JsonApiResource, calculateChange: true): string[];
|
|
17
|
+
pushData(data: JsonApiResource, calculateChange?: false): void;
|
|
18
|
+
pushData(data: JsonApiResource, calculateChange?: boolean): string[] | void;
|
|
16
19
|
clientDidCreate(): void;
|
|
17
20
|
willCommit(): void;
|
|
18
21
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { DSModel } from './ds-model';
|
|
2
|
+
import type { Dict } from './utils';
|
|
1
3
|
/**
|
|
2
4
|
@module @ember-data/store
|
|
3
5
|
*/
|
|
@@ -13,4 +15,4 @@
|
|
|
13
15
|
The type belows allows for anything extending object.
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
|
-
export type RecordInstance =
|
|
18
|
+
export type RecordInstance = DSModel | Dict<unknown>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type InternalModel from '../system/model/internal-model';
|
|
2
|
+
import type { PromiseObject } from '../system/promise-proxies';
|
|
2
3
|
import { promiseObject } from '../system/promise-proxies';
|
|
3
|
-
import type {
|
|
4
|
-
import type { PromiseProxy } from '../ts-interfaces/promise-proxies';
|
|
4
|
+
import type { RecordInstance } from '../ts-interfaces/record-instance';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
@module @ember-data/store
|
|
@@ -18,7 +18,7 @@ import type { PromiseProxy } from '../ts-interfaces/promise-proxies';
|
|
|
18
18
|
export default function promiseRecord(
|
|
19
19
|
internalModelPromise: Promise<InternalModel>,
|
|
20
20
|
label: string
|
|
21
|
-
):
|
|
21
|
+
): PromiseObject<RecordInstance> {
|
|
22
22
|
let toReturn = internalModelPromise.then((internalModel) => internalModel.getRecord());
|
|
23
23
|
|
|
24
24
|
return promiseObject(toReturn, label);
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ember-data/store",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0-alpha.2",
|
|
4
4
|
"description": "The default blueprint for ember-cli addons.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
"start": "ember serve"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@ember-data/canary-features": "4.
|
|
21
|
-
"@ember-data/private-build-infra": "4.
|
|
20
|
+
"@ember-data/canary-features": "4.5.0-alpha.2",
|
|
21
|
+
"@ember-data/private-build-infra": "4.5.0-alpha.2",
|
|
22
22
|
"@ember/string": "^3.0.0",
|
|
23
|
+
"@embroider/macros": "^1.2.0",
|
|
23
24
|
"@glimmer/tracking": "^1.0.4",
|
|
24
25
|
"ember-auto-import": "^2.2.4",
|
|
25
26
|
"ember-cached-decorator-polyfill": "^0.1.4",
|
|
@@ -28,14 +29,14 @@
|
|
|
28
29
|
"ember-cli-typescript": "^5.0.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
|
-
"@ember-data/unpublished-test-infra": "4.
|
|
32
|
+
"@ember-data/unpublished-test-infra": "4.5.0-alpha.2",
|
|
32
33
|
"@ember/optional-features": "^2.0.0",
|
|
33
34
|
"@ember/test-helpers": "^2.6.0",
|
|
34
35
|
"@types/ember": "^4.0.0",
|
|
35
36
|
"@types/rsvp": "^4.0.4",
|
|
36
37
|
"broccoli-asset-rev": "^3.0.0",
|
|
37
38
|
"ember-cli": "~4.3.0",
|
|
38
|
-
"ember-cli-dependency-checker": "^3.
|
|
39
|
+
"ember-cli-dependency-checker": "^3.3.1",
|
|
39
40
|
"ember-cli-htmlbars": "^6.0.1",
|
|
40
41
|
"ember-cli-inject-live-reload": "^2.0.2",
|
|
41
42
|
"ember-cli-sri": "^2.1.1",
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
"ember-maybe-import-regenerator": "^1.0.0",
|
|
47
48
|
"ember-qunit": "^5.1.5",
|
|
48
49
|
"ember-resolver": "^8.0.3",
|
|
49
|
-
"ember-source": "~4.
|
|
50
|
+
"ember-source": "~4.3.0",
|
|
50
51
|
"ember-source-channel-url": "^3.0.0",
|
|
51
52
|
"ember-try": "^2.0.0",
|
|
52
53
|
"loader.js": "^4.7.0",
|