@ember-data/store 4.4.0-alpha.8 → 4.4.0
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 +119 -130
- package/addon/-private/system/ds-model-store.ts +10 -1
- package/addon/-private/system/fetch-manager.ts +21 -48
- package/addon/-private/system/model/internal-model.ts +160 -264
- package/addon/-private/system/{promise-proxies.ts → promise-proxies.js} +21 -31
- package/addon/-private/system/{record-array-manager.ts → record-array-manager.js} +60 -87
- package/addon/-private/system/record-arrays/adapter-populated-record-array.js +95 -0
- package/addon/-private/system/record-arrays/{record-array.ts → record-array.js} +75 -96
- package/addon/-private/system/record-data-for.ts +0 -2
- package/addon/-private/system/references/belongs-to.ts +2 -3
- package/addon/-private/system/references/has-many.ts +2 -4
- package/addon/-private/system/schema-definition-service.ts +2 -2
- package/addon/-private/system/snapshot-record-array.ts +11 -12
- package/addon/-private/system/snapshot.ts +7 -24
- package/addon/-private/system/store/common.js +1 -24
- package/addon/-private/system/store/finders.js +5 -53
- package/addon/-private/system/store/internal-model-factory.ts +7 -8
- package/addon/-private/system/store/record-data-store-wrapper.ts +2 -7
- package/addon/-private/system/store/serializer-response.js +71 -0
- package/addon/-private/ts-interfaces/ds-model.ts +7 -15
- package/addon/-private/ts-interfaces/ember-data-json-api.ts +0 -3
- package/addon/-private/ts-interfaces/minimum-adapter-interface.ts +20 -19
- package/addon/-private/ts-interfaces/minimum-serializer-interface.ts +6 -27
- package/addon/-private/ts-interfaces/record-data.ts +1 -4
- package/addon/-private/ts-interfaces/record-instance.ts +1 -3
- package/addon/-private/ts-interfaces/store.ts +0 -1
- package/addon/-private/utils/promise-record.ts +3 -3
- package/index.js +0 -3
- package/package.json +6 -7
- package/addon/-private/system/promise-proxy-base.js +0 -7
- package/addon/-private/system/record-arrays/adapter-populated-record-array.ts +0 -129
- package/addon/-private/system/store/serializer-response.ts +0 -85
|
@@ -9,7 +9,6 @@ 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';
|
|
13
12
|
import type { RecordInstance } from '../../ts-interfaces/record-instance';
|
|
14
13
|
import constructResource from '../../utils/construct-resource';
|
|
15
14
|
import type CoreStore from '../core-store';
|
|
@@ -21,19 +20,19 @@ import WeakCache from '../weak-cache';
|
|
|
21
20
|
/**
|
|
22
21
|
@module @ember-data/store
|
|
23
22
|
*/
|
|
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
|
|
30
|
+
const RecordCache = new WeakCache<RecordInstance, StableRecordIdentifier>(DEBUG ? 'identifier' : '');
|
|
31
31
|
if (DEBUG) {
|
|
32
|
-
RecordCache._expectMsg = (key: RecordInstance
|
|
33
|
-
`${String(key)} is not a record instantiated by @ember-data/store`;
|
|
32
|
+
RecordCache._expectMsg = (key: RecordInstance) => `${key} is not a record instantiated by @ember-data/store`;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
export function peekRecordIdentifier(record:
|
|
35
|
+
export function peekRecordIdentifier(record: any): StableRecordIdentifier | undefined {
|
|
37
36
|
return RecordCache.get(record);
|
|
38
37
|
}
|
|
39
38
|
|
|
@@ -61,11 +60,11 @@ export function peekRecordIdentifier(record: RecordInstance | RecordData): Stabl
|
|
|
61
60
|
@param {Object} record a record instance previously obstained from the store.
|
|
62
61
|
@returns {StableRecordIdentifier}
|
|
63
62
|
*/
|
|
64
|
-
export function recordIdentifierFor(record: RecordInstance
|
|
63
|
+
export function recordIdentifierFor(record: RecordInstance): StableRecordIdentifier {
|
|
65
64
|
return RecordCache.getWithError(record);
|
|
66
65
|
}
|
|
67
66
|
|
|
68
|
-
export function setRecordIdentifier(record: RecordInstance
|
|
67
|
+
export function setRecordIdentifier(record: RecordInstance, identifier: StableRecordIdentifier): void {
|
|
69
68
|
if (DEBUG && RecordCache.has(record)) {
|
|
70
69
|
throw new Error(`${record} was already assigned an identifier`);
|
|
71
70
|
}
|
|
@@ -161,7 +160,7 @@ export default class InternalModelFactory {
|
|
|
161
160
|
TODO @runspired consider adding this to make polymorphism even nicer
|
|
162
161
|
if (HAS_RECORD_DATA_PACKAGE) {
|
|
163
162
|
if (identifier.type !== matchedIdentifier.type) {
|
|
164
|
-
const graphFor =
|
|
163
|
+
const graphFor = require('@ember-data/record-data/-private').graphFor;
|
|
165
164
|
graphFor(this).registerPolymorphicType(identifier.type, matchedIdentifier.type);
|
|
166
165
|
}
|
|
167
166
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { importSync } from '@embroider/macros';
|
|
2
|
-
|
|
3
1
|
import type { RelationshipDefinition } from '@ember-data/model/-private/system/relationships/relationship-meta';
|
|
4
2
|
import { HAS_RECORD_DATA_PACKAGE } from '@ember-data/private-build-infra';
|
|
5
3
|
|
|
@@ -12,7 +10,6 @@ import type {
|
|
|
12
10
|
RelationshipsSchema,
|
|
13
11
|
} from '../../ts-interfaces/record-data-schemas';
|
|
14
12
|
import type { RecordDataStoreWrapper as StoreWrapper } from '../../ts-interfaces/record-data-store-wrapper';
|
|
15
|
-
import { RecordInstance } from '../../ts-interfaces/record-instance';
|
|
16
13
|
import constructResource from '../../utils/construct-resource';
|
|
17
14
|
import type CoreStore from '../core-store';
|
|
18
15
|
import { internalModelFactoryFor } from './internal-model-factory';
|
|
@@ -29,9 +26,7 @@ let peekGraph;
|
|
|
29
26
|
if (HAS_RECORD_DATA_PACKAGE) {
|
|
30
27
|
let _peekGraph;
|
|
31
28
|
peekGraph = (wrapper) => {
|
|
32
|
-
_peekGraph =
|
|
33
|
-
_peekGraph ||
|
|
34
|
-
(importSync('@ember-data/record-data/-private') as typeof import('@ember-data/record-data/-private')).peekGraph;
|
|
29
|
+
_peekGraph = _peekGraph || require('@ember-data/record-data/-private').peekGraph;
|
|
35
30
|
return _peekGraph(wrapper);
|
|
36
31
|
};
|
|
37
32
|
}
|
|
@@ -225,7 +220,7 @@ export default class RecordDataStoreWrapper implements StoreWrapper {
|
|
|
225
220
|
return false;
|
|
226
221
|
}
|
|
227
222
|
|
|
228
|
-
const record = internalModel._record
|
|
223
|
+
const record = internalModel._record;
|
|
229
224
|
return record && !(record.isDestroyed || record.isDestroying);
|
|
230
225
|
}
|
|
231
226
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { assert } from '@ember/debug';
|
|
2
|
+
import { DEBUG } from '@glimmer/env';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
This is a helper method that validates a JSON API top-level document
|
|
6
|
+
|
|
7
|
+
The format of a document is described here:
|
|
8
|
+
http://jsonapi.org/format/#document-top-level
|
|
9
|
+
|
|
10
|
+
@internal
|
|
11
|
+
*/
|
|
12
|
+
export function validateDocumentStructure(doc) {
|
|
13
|
+
let errors = [];
|
|
14
|
+
if (!doc || typeof doc !== 'object') {
|
|
15
|
+
errors.push('Top level of a JSON API document must be an object');
|
|
16
|
+
} else {
|
|
17
|
+
if (!('data' in doc) && !('errors' in doc) && !('meta' in doc)) {
|
|
18
|
+
errors.push('One or more of the following keys must be present: "data", "errors", "meta".');
|
|
19
|
+
} else {
|
|
20
|
+
if ('data' in doc && 'errors' in doc) {
|
|
21
|
+
errors.push('Top level keys "errors" and "data" cannot both be present in a JSON API document');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if ('data' in doc) {
|
|
25
|
+
if (!(doc.data === null || Array.isArray(doc.data) || typeof doc.data === 'object')) {
|
|
26
|
+
errors.push('data must be null, an object, or an array');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if ('meta' in doc) {
|
|
30
|
+
if (typeof doc.meta !== 'object') {
|
|
31
|
+
errors.push('meta must be an object');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if ('errors' in doc) {
|
|
35
|
+
if (!Array.isArray(doc.errors)) {
|
|
36
|
+
errors.push('errors must be an array');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if ('links' in doc) {
|
|
40
|
+
if (typeof doc.links !== 'object') {
|
|
41
|
+
errors.push('links must be an object');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if ('jsonapi' in doc) {
|
|
45
|
+
if (typeof doc.jsonapi !== 'object') {
|
|
46
|
+
errors.push('jsonapi must be an object');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if ('included' in doc) {
|
|
50
|
+
if (typeof doc.included !== 'object') {
|
|
51
|
+
errors.push('included must be an array');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return errors;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function normalizeResponseHelper(serializer, store, modelClass, payload, id, requestType) {
|
|
60
|
+
let normalizedResponse = serializer.normalizeResponse(store, modelClass, payload, id, requestType);
|
|
61
|
+
let validationErrors = [];
|
|
62
|
+
if (DEBUG) {
|
|
63
|
+
validationErrors = validateDocumentStructure(normalizedResponse);
|
|
64
|
+
}
|
|
65
|
+
assert(
|
|
66
|
+
`normalizeResponse must return a valid JSON API document:\n\t* ${validationErrors.join('\n\t* ')}`,
|
|
67
|
+
validationErrors.length === 0
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return normalizedResponse;
|
|
71
|
+
}
|
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import EmberObject from '@ember/object';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import RSVP from 'rsvp';
|
|
4
4
|
|
|
5
|
-
import type CoreStore from '../system/core-store';
|
|
6
|
-
import type InternalModel from '../system/model/internal-model';
|
|
7
5
|
import type { JsonApiValidationError } from './record-data-json-api';
|
|
8
|
-
import type { AttributeSchema, RelationshipSchema
|
|
6
|
+
import type { AttributeSchema, RelationshipSchema } from './record-data-schemas';
|
|
7
|
+
import { RecordInstance } from './record-instance';
|
|
9
8
|
|
|
10
9
|
// Placeholder until model.js is typed
|
|
11
|
-
export interface DSModel extends EmberObject {
|
|
12
|
-
constructor: DSModelSchema;
|
|
13
|
-
store: CoreStore;
|
|
14
|
-
errors: Errors;
|
|
15
|
-
_internalModel: InternalModel;
|
|
10
|
+
export interface DSModel extends RecordInstance, EmberObject {
|
|
16
11
|
toString(): string;
|
|
17
|
-
save(): Promise<DSModel>;
|
|
12
|
+
save(): RSVP.Promise<DSModel>;
|
|
18
13
|
eachRelationship<T>(callback: (this: T, key: string, meta: RelationshipSchema) => void, binding?: T): void;
|
|
19
14
|
eachAttribute<T>(callback: (this: T, key: string, meta: AttributeSchema) => void, binding?: T): void;
|
|
20
15
|
invalidErrorsChanged(errors: JsonApiValidationError[]): void;
|
|
@@ -22,7 +17,7 @@ export interface DSModel extends EmberObject {
|
|
|
22
17
|
isDeleted: boolean;
|
|
23
18
|
deleteRecord(): void;
|
|
24
19
|
unloadRecord(): void;
|
|
25
|
-
|
|
20
|
+
errors: any;
|
|
26
21
|
}
|
|
27
22
|
|
|
28
23
|
// Implemented by both ShimModelClass and DSModel
|
|
@@ -44,7 +39,4 @@ export interface ModelSchema {
|
|
|
44
39
|
// once we can type it.
|
|
45
40
|
export interface DSModelSchema extends ModelSchema {
|
|
46
41
|
isModel: true;
|
|
47
|
-
relationshipsObject: RelationshipsSchema;
|
|
48
|
-
extend(...mixins: unknown[]): DSModelSchema;
|
|
49
|
-
reopenClass(...mixins: unknown[]): void;
|
|
50
42
|
}
|
|
@@ -125,9 +125,6 @@ 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[];
|
|
131
128
|
}
|
|
132
129
|
|
|
133
130
|
export interface EmptyResourceDocument extends Document {
|
|
@@ -1,3 +1,7 @@
|
|
|
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
|
+
|
|
1
5
|
import type Store from '../system/core-store';
|
|
2
6
|
import type AdapterPopulatedRecordArray from '../system/record-arrays/adapter-populated-record-array';
|
|
3
7
|
import type Snapshot from '../system/snapshot';
|
|
@@ -7,12 +11,7 @@ import type { RelationshipSchema } from './record-data-schemas';
|
|
|
7
11
|
import type { Dict } from './utils';
|
|
8
12
|
|
|
9
13
|
type Group = Snapshot[];
|
|
10
|
-
|
|
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[];
|
|
14
|
+
|
|
16
15
|
/**
|
|
17
16
|
* @module @ember-data/adapter
|
|
18
17
|
*/
|
|
@@ -27,7 +26,7 @@ export type AdapterPayload = Dict<unknown> | unknown[];
|
|
|
27
26
|
@class MinimumAdapterInterface
|
|
28
27
|
@public
|
|
29
28
|
*/
|
|
30
|
-
|
|
29
|
+
interface Adapter {
|
|
31
30
|
/**
|
|
32
31
|
* `adapter.findRecord` takes a request for a resource of a given `type` and `id` combination
|
|
33
32
|
* and should return a `Promise` which fulfills with data for a single resource matching that
|
|
@@ -55,7 +54,7 @@ export interface MinimumAdapterInterface {
|
|
|
55
54
|
* @param {Snapshot} snapshot
|
|
56
55
|
* @return {Promise} a promise resolving with resource data to feed to the associated serializer
|
|
57
56
|
*/
|
|
58
|
-
findRecord(store: Store, schema: ModelSchema, id: string, snapshot: Snapshot): Promise<
|
|
57
|
+
findRecord(store: Store, schema: ModelSchema, id: string, snapshot: Snapshot): Promise<unknown>;
|
|
59
58
|
|
|
60
59
|
/**
|
|
61
60
|
* `adapter.findAll` takes a request for resources of a given `type` and should return
|
|
@@ -92,7 +91,7 @@ export interface MinimumAdapterInterface {
|
|
|
92
91
|
schema: ModelSchema,
|
|
93
92
|
sinceToken: null,
|
|
94
93
|
snapshotRecordArray: SnapshotRecordArray
|
|
95
|
-
): Promise<
|
|
94
|
+
): Promise<unknown>;
|
|
96
95
|
|
|
97
96
|
/**
|
|
98
97
|
* `adapter.query` takes a request for resources of a given `type` and should return
|
|
@@ -128,10 +127,10 @@ export interface MinimumAdapterInterface {
|
|
|
128
127
|
query(
|
|
129
128
|
store: Store,
|
|
130
129
|
schema: ModelSchema,
|
|
131
|
-
query: Dict<
|
|
130
|
+
query: Dict<any>,
|
|
132
131
|
recordArray: AdapterPopulatedRecordArray,
|
|
133
132
|
options: { adapterOptions?: unknown }
|
|
134
|
-
): Promise<
|
|
133
|
+
): Promise<unknown>;
|
|
135
134
|
|
|
136
135
|
/**
|
|
137
136
|
* `adapter.queryRecord` takes a request for resource of a given `type` and should return
|
|
@@ -159,9 +158,9 @@ export interface MinimumAdapterInterface {
|
|
|
159
158
|
queryRecord(
|
|
160
159
|
store: Store,
|
|
161
160
|
schema: ModelSchema,
|
|
162
|
-
query: Dict<
|
|
161
|
+
query: Dict<any>,
|
|
163
162
|
options: { adapterOptions?: unknown }
|
|
164
|
-
): Promise<
|
|
163
|
+
): Promise<unknown>;
|
|
165
164
|
|
|
166
165
|
/**
|
|
167
166
|
* `adapter.createRecord` takes a request to create a resource of a given `type` and should
|
|
@@ -214,7 +213,7 @@ export interface MinimumAdapterInterface {
|
|
|
214
213
|
* @param {Snapshot} snapshot
|
|
215
214
|
* @return {Promise} a promise resolving with resource data to feed to the associated serializer
|
|
216
215
|
*/
|
|
217
|
-
createRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<
|
|
216
|
+
createRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<unknown>;
|
|
218
217
|
|
|
219
218
|
/**
|
|
220
219
|
* `adapter.updateRecord` takes a request to update a resource of a given `type` and should
|
|
@@ -266,7 +265,7 @@ export interface MinimumAdapterInterface {
|
|
|
266
265
|
* the type, attributes and relationships of the primary type associated with the request.
|
|
267
266
|
* @param {Snapshot} snapshot
|
|
268
267
|
*/
|
|
269
|
-
updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<
|
|
268
|
+
updateRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<unknown>;
|
|
270
269
|
|
|
271
270
|
/**
|
|
272
271
|
* `adapter.deleteRecord` takes a request to delete a resource of a given `type` and
|
|
@@ -294,7 +293,7 @@ export interface MinimumAdapterInterface {
|
|
|
294
293
|
* @param {Snapshot} snapshot A Snapshot containing the record's current data
|
|
295
294
|
* @return
|
|
296
295
|
*/
|
|
297
|
-
deleteRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<
|
|
296
|
+
deleteRecord(store: Store, schema: ModelSchema, snapshot: Snapshot): Promise<unknown>;
|
|
298
297
|
|
|
299
298
|
/**
|
|
300
299
|
* `adapter.findBelongsTo` takes a request to fetch a related resource located at a
|
|
@@ -331,7 +330,7 @@ export interface MinimumAdapterInterface {
|
|
|
331
330
|
snapshot: Snapshot,
|
|
332
331
|
relatedLink: string,
|
|
333
332
|
relationship: RelationshipSchema
|
|
334
|
-
): Promise<
|
|
333
|
+
): Promise<unknown>;
|
|
335
334
|
|
|
336
335
|
/**
|
|
337
336
|
* `adapter.findHasMany` takes a request to fetch a related resource collection located
|
|
@@ -369,7 +368,7 @@ export interface MinimumAdapterInterface {
|
|
|
369
368
|
snapshot: Snapshot,
|
|
370
369
|
relatedLink: string,
|
|
371
370
|
relationship: RelationshipSchema
|
|
372
|
-
): Promise<
|
|
371
|
+
): Promise<unknown>;
|
|
373
372
|
|
|
374
373
|
/**
|
|
375
374
|
* ⚠️ This Method is only called if `coalesceFindRequests` is `true`. The array passed to it is determined
|
|
@@ -400,7 +399,7 @@ export interface MinimumAdapterInterface {
|
|
|
400
399
|
* @param {Array<Snapshot>} snapshots An array of snapshots of the available data for the resources to fetch
|
|
401
400
|
* @return {Promise} a promise resolving with resource data to feed to the associated serializer
|
|
402
401
|
*/
|
|
403
|
-
findMany?(store: Store, schema: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<
|
|
402
|
+
findMany?(store: Store, schema: ModelSchema, ids: string[], snapshots: Snapshot[]): Promise<unknown>;
|
|
404
403
|
|
|
405
404
|
/**
|
|
406
405
|
* This method provides the ability to generate an ID to assign to a new record whenever `store.createRecord`
|
|
@@ -582,3 +581,5 @@ export interface MinimumAdapterInterface {
|
|
|
582
581
|
*/
|
|
583
582
|
destroy?(): void;
|
|
584
583
|
}
|
|
584
|
+
|
|
585
|
+
export default Adapter;
|
|
@@ -4,21 +4,10 @@ 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';
|
|
8
7
|
import type { Dict } from './utils';
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
| 'findRecord'
|
|
13
|
-
| 'queryRecord'
|
|
14
|
-
| 'findAll'
|
|
15
|
-
| 'findBelongsTo'
|
|
16
|
-
| 'findHasMany'
|
|
17
|
-
| 'findMany'
|
|
18
|
-
| 'query'
|
|
19
|
-
| 'createRecord'
|
|
20
|
-
| 'deleteRecord'
|
|
21
|
-
| 'updateRecord';
|
|
9
|
+
type OptionsHash = Dict<any>;
|
|
10
|
+
|
|
22
11
|
/**
|
|
23
12
|
@module @ember-data/serializer
|
|
24
13
|
*/
|
|
@@ -33,7 +22,7 @@ export type RequestType =
|
|
|
33
22
|
@class MinimumSerializerInterface
|
|
34
23
|
@public
|
|
35
24
|
*/
|
|
36
|
-
|
|
25
|
+
interface Serializer {
|
|
37
26
|
/**
|
|
38
27
|
* This method is responsible for normalizing the value resolved from the promise returned
|
|
39
28
|
* by an Adapter request into the format expected by the `Store`.
|
|
@@ -67,7 +56,7 @@ export interface MinimumSerializerInterface {
|
|
|
67
56
|
normalizeResponse(
|
|
68
57
|
store: Store,
|
|
69
58
|
schema: ModelSchema,
|
|
70
|
-
rawPayload:
|
|
59
|
+
rawPayload: JSONObject,
|
|
71
60
|
id: string | null,
|
|
72
61
|
requestType:
|
|
73
62
|
| 'findRecord'
|
|
@@ -242,16 +231,6 @@ export interface MinimumSerializerInterface {
|
|
|
242
231
|
* @returns {void}
|
|
243
232
|
*/
|
|
244
233
|
pushPayload?(store: Store, rawPayload: JSONObject): void;
|
|
245
|
-
|
|
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
234
|
}
|
|
235
|
+
|
|
236
|
+
export default Serializer;
|
|
@@ -12,10 +12,7 @@ export interface ChangedAttributesHash {
|
|
|
12
12
|
|
|
13
13
|
export interface RecordData {
|
|
14
14
|
getResourceIdentifier(): RecordIdentifier | undefined;
|
|
15
|
-
|
|
16
|
-
pushData(data: JsonApiResource, calculateChange: true): string[];
|
|
17
|
-
pushData(data: JsonApiResource, calculateChange?: false): void;
|
|
18
|
-
pushData(data: JsonApiResource, calculateChange?: boolean): string[] | void;
|
|
15
|
+
pushData(data: JsonApiResource, calculateChange?: boolean): void;
|
|
19
16
|
clientDidCreate(): void;
|
|
20
17
|
willCommit(): void;
|
|
21
18
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { DSModel } from './ds-model';
|
|
2
|
-
import type { Dict } from './utils';
|
|
3
1
|
/**
|
|
4
2
|
@module @ember-data/store
|
|
5
3
|
*/
|
|
@@ -15,4 +13,4 @@ import type { Dict } from './utils';
|
|
|
15
13
|
The type belows allows for anything extending object.
|
|
16
14
|
*/
|
|
17
15
|
|
|
18
|
-
export type RecordInstance =
|
|
16
|
+
export type RecordInstance = Object;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type InternalModel from '../system/model/internal-model';
|
|
2
|
-
import type { PromiseObject } from '../system/promise-proxies';
|
|
3
2
|
import { promiseObject } from '../system/promise-proxies';
|
|
4
|
-
import type {
|
|
3
|
+
import type { DSModel } from '../ts-interfaces/ds-model';
|
|
4
|
+
import type { PromiseProxy } from '../ts-interfaces/promise-proxies';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
@module @ember-data/store
|
|
@@ -18,7 +18,7 @@ import type { RecordInstance } from '../ts-interfaces/record-instance';
|
|
|
18
18
|
export default function promiseRecord(
|
|
19
19
|
internalModelPromise: Promise<InternalModel>,
|
|
20
20
|
label: string
|
|
21
|
-
):
|
|
21
|
+
): PromiseProxy<DSModel> {
|
|
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.4.0
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "The default blueprint for ember-cli addons.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ember-addon"
|
|
@@ -17,10 +17,9 @@
|
|
|
17
17
|
"start": "ember serve"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@ember-data/canary-features": "4.4.0
|
|
21
|
-
"@ember-data/private-build-infra": "4.4.0
|
|
20
|
+
"@ember-data/canary-features": "4.4.0",
|
|
21
|
+
"@ember-data/private-build-infra": "4.4.0",
|
|
22
22
|
"@ember/string": "^3.0.0",
|
|
23
|
-
"@embroider/macros": "^1.2.0",
|
|
24
23
|
"@glimmer/tracking": "^1.0.4",
|
|
25
24
|
"ember-auto-import": "^2.2.4",
|
|
26
25
|
"ember-cached-decorator-polyfill": "^0.1.4",
|
|
@@ -29,13 +28,13 @@
|
|
|
29
28
|
"ember-cli-typescript": "^5.0.0"
|
|
30
29
|
},
|
|
31
30
|
"devDependencies": {
|
|
32
|
-
"@ember-data/unpublished-test-infra": "4.4.0
|
|
31
|
+
"@ember-data/unpublished-test-infra": "4.4.0",
|
|
33
32
|
"@ember/optional-features": "^2.0.0",
|
|
34
33
|
"@ember/test-helpers": "^2.6.0",
|
|
35
34
|
"@types/ember": "^4.0.0",
|
|
36
35
|
"@types/rsvp": "^4.0.4",
|
|
37
36
|
"broccoli-asset-rev": "^3.0.0",
|
|
38
|
-
"ember-cli": "~4.
|
|
37
|
+
"ember-cli": "~4.3.0",
|
|
39
38
|
"ember-cli-dependency-checker": "^3.2.0",
|
|
40
39
|
"ember-cli-htmlbars": "^6.0.1",
|
|
41
40
|
"ember-cli-inject-live-reload": "^2.0.2",
|
|
@@ -47,7 +46,7 @@
|
|
|
47
46
|
"ember-maybe-import-regenerator": "^1.0.0",
|
|
48
47
|
"ember-qunit": "^5.1.5",
|
|
49
48
|
"ember-resolver": "^8.0.3",
|
|
50
|
-
"ember-source": "~4.
|
|
49
|
+
"ember-source": "~4.4.0",
|
|
51
50
|
"ember-source-channel-url": "^3.0.0",
|
|
52
51
|
"ember-try": "^2.0.0",
|
|
53
52
|
"loader.js": "^4.7.0",
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import ArrayProxy from '@ember/array/proxy';
|
|
2
|
-
import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
|
|
3
|
-
import ObjectProxy from '@ember/object/proxy';
|
|
4
|
-
|
|
5
|
-
export const PromiseArrayProxy = ArrayProxy.extend(PromiseProxyMixin);
|
|
6
|
-
|
|
7
|
-
export const PromiseObjectProxy = ObjectProxy.extend(PromiseProxyMixin);
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import type NativeArray from '@ember/array/-private/native-array';
|
|
2
|
-
import { assert } from '@ember/debug';
|
|
3
|
-
|
|
4
|
-
import type { PromiseArray, RecordArrayManager } from 'ember-data/-private';
|
|
5
|
-
|
|
6
|
-
import type { CollectionResourceDocument, Links, Meta, PaginationLinks } from '../../ts-interfaces/ember-data-json-api';
|
|
7
|
-
import type { StableRecordIdentifier } from '../../ts-interfaces/identifier';
|
|
8
|
-
import type { RecordInstance } from '../../ts-interfaces/record-instance';
|
|
9
|
-
import type { FindOptions } from '../../ts-interfaces/store';
|
|
10
|
-
import type { Dict } from '../../ts-interfaces/utils';
|
|
11
|
-
import type CoreStore from '../core-store';
|
|
12
|
-
import { promiseArray } from '../promise-proxies';
|
|
13
|
-
import SnapshotRecordArray from '../snapshot-record-array';
|
|
14
|
-
import RecordArray from './record-array';
|
|
15
|
-
|
|
16
|
-
export interface AdapterPopulatedRecordArrayCreateArgs {
|
|
17
|
-
modelName: string;
|
|
18
|
-
store: CoreStore;
|
|
19
|
-
manager: RecordArrayManager;
|
|
20
|
-
content: NativeArray<StableRecordIdentifier>;
|
|
21
|
-
isLoaded: boolean;
|
|
22
|
-
query?: Dict<unknown>;
|
|
23
|
-
meta?: Meta;
|
|
24
|
-
links?: Links | PaginationLinks | null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
@module @ember-data/store
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
Represents an ordered list of records whose order and membership is
|
|
33
|
-
determined by the adapter. For example, a query sent to the adapter
|
|
34
|
-
may trigger a search on the server, whose results would be loaded
|
|
35
|
-
into an instance of the `AdapterPopulatedRecordArray`.
|
|
36
|
-
|
|
37
|
-
This class should not be imported and instantiated by consuming applications.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
If you want to update the array and get the latest records from the
|
|
42
|
-
adapter, you can invoke [`update()`](AdapterPopulatedRecordArray/methods/update?anchor=update):
|
|
43
|
-
|
|
44
|
-
Example
|
|
45
|
-
|
|
46
|
-
```javascript
|
|
47
|
-
// GET /users?isAdmin=true
|
|
48
|
-
store.query('user', { isAdmin: true }).then(function(admins) {
|
|
49
|
-
|
|
50
|
-
admins.then(function() {
|
|
51
|
-
console.log(admins.get("length")); // 42
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// somewhere later in the app code, when new admins have been created
|
|
55
|
-
// in the meantime
|
|
56
|
-
//
|
|
57
|
-
// GET /users?isAdmin=true
|
|
58
|
-
admins.update().then(function() {
|
|
59
|
-
admins.get('isUpdating'); // false
|
|
60
|
-
console.log(admins.get("length")); // 123
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
admins.get('isUpdating'); // true
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
@class AdapterPopulatedRecordArray
|
|
68
|
-
@public
|
|
69
|
-
@extends RecordArray
|
|
70
|
-
*/
|
|
71
|
-
export default class AdapterPopulatedRecordArray extends RecordArray {
|
|
72
|
-
declare links: Links | PaginationLinks | null;
|
|
73
|
-
declare meta: Dict<unknown> | null;
|
|
74
|
-
declare query: Dict<unknown> | null;
|
|
75
|
-
|
|
76
|
-
init(props?: AdapterPopulatedRecordArrayCreateArgs) {
|
|
77
|
-
assert(`Cannot initialize AdapterPopulatedRecordArray with isUpdating`, !props || !('isUpdating' in props));
|
|
78
|
-
super.init();
|
|
79
|
-
this.query = this.query || null;
|
|
80
|
-
this.links = this.links || null;
|
|
81
|
-
this.meta = this.meta || null;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
replace() {
|
|
85
|
-
throw new Error(`The result of a server query (on ${this.modelName}) is immutable.`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
_update(): PromiseArray<RecordInstance, AdapterPopulatedRecordArray> {
|
|
89
|
-
const { store, query } = this;
|
|
90
|
-
|
|
91
|
-
// TODO save options from initial request?
|
|
92
|
-
return promiseArray(store._query(this.modelName, query, this, {}));
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
_setObjects(identifiers: StableRecordIdentifier[], payload: CollectionResourceDocument) {
|
|
96
|
-
// TODO: initial load should not cause change events at all, only
|
|
97
|
-
// subsequent. This requires changing the public api of adapter.query, but
|
|
98
|
-
// hopefully we can do that soon.
|
|
99
|
-
this.content.setObjects(identifiers);
|
|
100
|
-
|
|
101
|
-
this.setProperties({
|
|
102
|
-
isLoaded: true,
|
|
103
|
-
isUpdating: false,
|
|
104
|
-
// TODO this assign kills the root reference but a deep-copy would be required
|
|
105
|
-
// for both meta and links to actually not be by-ref. We whould likely change
|
|
106
|
-
// this to a dev-only deep-freeze.
|
|
107
|
-
meta: Object.assign({}, payload.meta),
|
|
108
|
-
links: Object.assign({}, payload.links),
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
this.manager._associateWithRecordArray(identifiers, this);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
_createSnapshot(options: FindOptions) {
|
|
115
|
-
// this is private for users, but public for ember-data internals
|
|
116
|
-
// meta will only be present for an AdapterPopulatedRecordArray
|
|
117
|
-
return new SnapshotRecordArray(this, this.meta, options);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
@method _setIdentifiers
|
|
122
|
-
@param {StableRecordIdentifier[]} identifiers
|
|
123
|
-
@param {Object} payload normalized payload
|
|
124
|
-
@private
|
|
125
|
-
*/
|
|
126
|
-
_setIdentifiers(identifiers: StableRecordIdentifier[], payload: CollectionResourceDocument): void {
|
|
127
|
-
this._setObjects(identifiers, payload);
|
|
128
|
-
}
|
|
129
|
-
}
|