@ember-data/store 4.5.0-beta.0 → 4.5.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/backburner.js → backburner.js} +0 -0
- package/addon/-private/{system/coerce-id.ts → coerce-id.ts} +0 -0
- package/addon/-private/{system/store/common.js → common.js} +0 -0
- package/addon/-private/{system/core-store.ts → core-store.ts} +467 -1253
- package/addon/-private/{system/errors-utils.js → errors-utils.js} +7 -6
- package/addon/-private/{system/fetch-manager.ts → fetch-manager.ts} +72 -42
- package/addon/-private/finders.js +107 -0
- package/addon/-private/identifer-debug-consts.ts +3 -0
- package/addon/-private/{identifiers/cache.ts → identifier-cache.ts} +26 -14
- package/addon/-private/{system/identity-map.ts → identity-map.ts} +2 -1
- package/addon/-private/index.ts +17 -17
- package/addon/-private/instance-cache.ts +387 -0
- package/addon/-private/{system/store/internal-model-factory.ts → internal-model-factory.ts} +25 -19
- package/addon/-private/{system/internal-model-map.ts → internal-model-map.ts} +9 -5
- package/addon/-private/model/internal-model.ts +602 -0
- package/addon/-private/{system/references/record.ts → model/record-reference.ts} +23 -36
- package/addon/-private/{system/model → model}/shim-model-class.ts +19 -14
- package/addon/-private/{system/normalize-model-name.ts → normalize-model-name.ts} +0 -0
- package/addon/-private/{system/promise-proxies.ts → promise-proxies.ts} +12 -5
- package/addon/-private/{system/promise-proxy-base.js → promise-proxy-base.js} +0 -0
- package/addon/-private/{system/record-array-manager.ts → record-array-manager.ts} +19 -18
- package/addon/-private/{system/record-arrays → record-arrays}/adapter-populated-record-array.ts +11 -10
- package/addon/-private/{system/record-arrays → record-arrays}/record-array.ts +37 -19
- package/addon/-private/record-data-for.ts +39 -0
- package/addon/-private/{system/store/record-data-store-wrapper.ts → record-data-store-wrapper.ts} +21 -26
- package/addon/-private/{system/record-notification-manager.ts → record-notification-manager.ts} +8 -3
- package/addon/-private/{system/request-cache.ts → request-cache.ts} +5 -6
- package/addon/-private/{system/schema-definition-service.ts → schema-definition-service.ts} +30 -14
- package/addon/-private/{system/store/serializer-response.ts → serializer-response.ts} +7 -6
- package/addon/-private/{system/snapshot-record-array.ts → snapshot-record-array.ts} +27 -8
- package/addon/-private/{system/snapshot.ts → snapshot.ts} +54 -39
- package/addon/-private/utils/construct-resource.ts +7 -3
- package/addon/-private/utils/promise-record.ts +9 -18
- package/addon/-private/{system/weak-cache.ts → weak-cache.ts} +2 -2
- package/addon/index.ts +1 -0
- package/package.json +21 -20
- package/addon/-private/identifiers/is-stable-identifier.ts +0 -18
- package/addon/-private/identifiers/utils/uuid-v4.ts +0 -80
- package/addon/-private/system/ds-model-store.ts +0 -136
- package/addon/-private/system/model/internal-model.ts +0 -1303
- package/addon/-private/system/model/states.js +0 -736
- package/addon/-private/system/record-arrays.ts +0 -8
- package/addon/-private/system/record-data-for.ts +0 -54
- package/addon/-private/system/references/belongs-to.ts +0 -406
- package/addon/-private/system/references/has-many.ts +0 -487
- package/addon/-private/system/references/reference.ts +0 -205
- package/addon/-private/system/references.js +0 -9
- package/addon/-private/system/store/finders.js +0 -412
- package/addon/-private/ts-interfaces/ds-model.ts +0 -50
- package/addon/-private/ts-interfaces/ember-data-json-api.ts +0 -145
- package/addon/-private/ts-interfaces/fetch-manager.ts +0 -44
- package/addon/-private/ts-interfaces/identifier.ts +0 -246
- package/addon/-private/ts-interfaces/minimum-adapter-interface.ts +0 -584
- package/addon/-private/ts-interfaces/minimum-serializer-interface.ts +0 -257
- package/addon/-private/ts-interfaces/promise-proxies.ts +0 -3
- package/addon/-private/ts-interfaces/record-data-json-api.ts +0 -29
- package/addon/-private/ts-interfaces/record-data-record-wrapper.ts +0 -46
- package/addon/-private/ts-interfaces/record-data-schemas.ts +0 -45
- package/addon/-private/ts-interfaces/record-data-store-wrapper.ts +0 -56
- package/addon/-private/ts-interfaces/record-data.ts +0 -72
- package/addon/-private/ts-interfaces/record-instance.ts +0 -18
- package/addon/-private/ts-interfaces/schema-definition-service.ts +0 -12
- package/addon/-private/ts-interfaces/store.ts +0 -10
- package/addon/-private/ts-interfaces/utils.ts +0 -6
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
import { assert, deprecate } from '@ember/debug';
|
|
2
|
-
import { DEBUG } from '@glimmer/env';
|
|
3
|
-
|
|
4
|
-
import { Promise } from 'rsvp';
|
|
5
|
-
|
|
6
|
-
import { DEPRECATE_RSVP_PROMISE } from '@ember-data/private-build-infra/deprecations';
|
|
7
|
-
|
|
8
|
-
import { _bind, _guard, _objectIsAlive, guardDestroyedStore } from './common';
|
|
9
|
-
import { normalizeResponseHelper } from './serializer-response';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
@module @ember-data/store
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
function payloadIsNotBlank(adapterPayload) {
|
|
16
|
-
if (Array.isArray(adapterPayload)) {
|
|
17
|
-
return true;
|
|
18
|
-
} else {
|
|
19
|
-
return Object.keys(adapterPayload || {}).length;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function iterateData(data, fn) {
|
|
24
|
-
if (Array.isArray(data)) {
|
|
25
|
-
return data.map(fn);
|
|
26
|
-
} else {
|
|
27
|
-
return fn(data);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// sync
|
|
32
|
-
// iterate over records in payload.data
|
|
33
|
-
// for each record
|
|
34
|
-
// assert that record.relationships[inverse] is either undefined (so we can fix it)
|
|
35
|
-
// or provide a data: {id, type} that matches the record that requested it
|
|
36
|
-
// return the relationship data for the parent
|
|
37
|
-
function syncRelationshipDataFromLink(store, payload, parentInternalModel, relationship) {
|
|
38
|
-
// ensure the right hand side (incoming payload) points to the parent record that
|
|
39
|
-
// requested this relationship
|
|
40
|
-
let relationshipData = payload.data
|
|
41
|
-
? iterateData(payload.data, (data, index) => {
|
|
42
|
-
const { id, type } = data;
|
|
43
|
-
ensureRelationshipIsSetToParent(data, parentInternalModel, store, relationship, index);
|
|
44
|
-
return { id, type };
|
|
45
|
-
})
|
|
46
|
-
: null;
|
|
47
|
-
|
|
48
|
-
const relatedDataHash = {};
|
|
49
|
-
|
|
50
|
-
if ('meta' in payload) {
|
|
51
|
-
relatedDataHash.meta = payload.meta;
|
|
52
|
-
}
|
|
53
|
-
if ('links' in payload) {
|
|
54
|
-
relatedDataHash.links = payload.links;
|
|
55
|
-
}
|
|
56
|
-
if ('data' in payload) {
|
|
57
|
-
relatedDataHash.data = relationshipData;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// now, push the left hand side (the parent record) to ensure things are in sync, since
|
|
61
|
-
// the payload will be pushed with store._push
|
|
62
|
-
const parentPayload = {
|
|
63
|
-
id: parentInternalModel.id,
|
|
64
|
-
type: parentInternalModel.modelName,
|
|
65
|
-
relationships: {
|
|
66
|
-
[relationship.key]: relatedDataHash,
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
if (!Array.isArray(payload.included)) {
|
|
71
|
-
payload.included = [];
|
|
72
|
-
}
|
|
73
|
-
payload.included.push(parentPayload);
|
|
74
|
-
|
|
75
|
-
return payload;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function ensureRelationshipIsSetToParent(payload, parentInternalModel, store, parentRelationship, index) {
|
|
79
|
-
let { id, type } = payload;
|
|
80
|
-
|
|
81
|
-
if (!payload.relationships) {
|
|
82
|
-
payload.relationships = {};
|
|
83
|
-
}
|
|
84
|
-
let { relationships } = payload;
|
|
85
|
-
|
|
86
|
-
let inverse = getInverse(store, parentInternalModel, parentRelationship, type);
|
|
87
|
-
if (inverse) {
|
|
88
|
-
let { inverseKey, kind } = inverse;
|
|
89
|
-
|
|
90
|
-
let relationshipData = relationships[inverseKey] && relationships[inverseKey].data;
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
DEBUG &&
|
|
94
|
-
typeof relationshipData !== 'undefined' &&
|
|
95
|
-
!relationshipDataPointsToParent(relationshipData, parentInternalModel)
|
|
96
|
-
) {
|
|
97
|
-
let inspect = function inspect(thing) {
|
|
98
|
-
return `'${JSON.stringify(thing)}'`;
|
|
99
|
-
};
|
|
100
|
-
let quotedType = inspect(type);
|
|
101
|
-
let quotedInverse = inspect(inverseKey);
|
|
102
|
-
let expected = inspect({
|
|
103
|
-
id: parentInternalModel.id,
|
|
104
|
-
type: parentInternalModel.modelName,
|
|
105
|
-
});
|
|
106
|
-
let expectedModel = `${parentInternalModel.modelName}:${parentInternalModel.id}`;
|
|
107
|
-
let got = inspect(relationshipData);
|
|
108
|
-
let prefix = typeof index === 'number' ? `data[${index}]` : `data`;
|
|
109
|
-
let path = `${prefix}.relationships.${inverseKey}.data`;
|
|
110
|
-
let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null;
|
|
111
|
-
let relationshipFetched = `${expectedModel}.${parentRelationship.kind}("${parentRelationship.name}")`;
|
|
112
|
-
let includedRecord = `<${type}:${id}>`;
|
|
113
|
-
let message = [
|
|
114
|
-
`Encountered mismatched relationship: Ember Data expected ${path} in the payload from ${relationshipFetched} to include ${expected} but got ${got} instead.\n`,
|
|
115
|
-
`The ${includedRecord} record loaded at ${prefix} in the payload specified ${other} as its ${quotedInverse}, but should have specified ${expectedModel} (the record the relationship is being loaded from) as its ${quotedInverse} instead.`,
|
|
116
|
-
`This could mean that the response for ${relationshipFetched} may have accidentally returned ${quotedType} records that aren't related to ${expectedModel} and could be related to a different ${parentInternalModel.modelName} record instead.`,
|
|
117
|
-
`Ember Data has corrected the ${includedRecord} record's ${quotedInverse} relationship to ${expectedModel} so that ${relationshipFetched} will include ${includedRecord}.`,
|
|
118
|
-
`Please update the response from the server or change your serializer to either ensure that the response for only includes ${quotedType} records that specify ${expectedModel} as their ${quotedInverse}, or omit the ${quotedInverse} relationship from the response.`,
|
|
119
|
-
].join('\n');
|
|
120
|
-
|
|
121
|
-
assert(message);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (kind !== 'hasMany' || typeof relationshipData !== 'undefined') {
|
|
125
|
-
relationships[inverseKey] = relationships[inverseKey] || {};
|
|
126
|
-
relationships[inverseKey].data = fixRelationshipData(relationshipData, kind, parentInternalModel);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function getInverse(store, parentInternalModel, parentRelationship, type) {
|
|
132
|
-
return recordDataFindInverseRelationshipInfo(store, parentInternalModel, parentRelationship, type);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function recordDataFindInverseRelationshipInfo({ _storeWrapper }, parentInternalModel, parentRelationship, type) {
|
|
136
|
-
let { name: lhs_relationshipName } = parentRelationship;
|
|
137
|
-
let { modelName } = parentInternalModel;
|
|
138
|
-
let inverseKey = _storeWrapper.inverseForRelationship(modelName, lhs_relationshipName);
|
|
139
|
-
|
|
140
|
-
if (inverseKey) {
|
|
141
|
-
let {
|
|
142
|
-
meta: { kind },
|
|
143
|
-
} = _storeWrapper.relationshipsDefinitionFor(type)[inverseKey];
|
|
144
|
-
return {
|
|
145
|
-
inverseKey,
|
|
146
|
-
kind,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function relationshipDataPointsToParent(relationshipData, internalModel) {
|
|
152
|
-
if (relationshipData === null) {
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (Array.isArray(relationshipData)) {
|
|
157
|
-
if (relationshipData.length === 0) {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
for (let i = 0; i < relationshipData.length; i++) {
|
|
161
|
-
let entry = relationshipData[i];
|
|
162
|
-
if (validateRelationshipEntry(entry, internalModel)) {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
} else {
|
|
167
|
-
return validateRelationshipEntry(relationshipData, internalModel);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function fixRelationshipData(relationshipData, relationshipKind, { id, modelName }) {
|
|
174
|
-
let parentRelationshipData = {
|
|
175
|
-
id,
|
|
176
|
-
type: modelName,
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
let payload;
|
|
180
|
-
|
|
181
|
-
if (relationshipKind === 'hasMany') {
|
|
182
|
-
payload = relationshipData || [];
|
|
183
|
-
if (relationshipData) {
|
|
184
|
-
// these arrays could be massive so this is better than filter
|
|
185
|
-
// Note: this is potentially problematic if type/id are not in the
|
|
186
|
-
// same state of normalization.
|
|
187
|
-
let found = relationshipData.find((v) => {
|
|
188
|
-
return v.type === parentRelationshipData.type && v.id === parentRelationshipData.id;
|
|
189
|
-
});
|
|
190
|
-
if (!found) {
|
|
191
|
-
payload.push(parentRelationshipData);
|
|
192
|
-
}
|
|
193
|
-
} else {
|
|
194
|
-
payload.push(parentRelationshipData);
|
|
195
|
-
}
|
|
196
|
-
} else {
|
|
197
|
-
payload = relationshipData || {};
|
|
198
|
-
Object.assign(payload, parentRelationshipData);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return payload;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function validateRelationshipEntry({ id }, { id: parentModelID }) {
|
|
205
|
-
return id && id.toString() === parentModelID;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export function _findHasMany(adapter, store, internalModel, link, relationship, options) {
|
|
209
|
-
let snapshot = internalModel.createSnapshot(options);
|
|
210
|
-
let modelClass = store.modelFor(relationship.type);
|
|
211
|
-
let useLink = !link || typeof link === 'string';
|
|
212
|
-
let relatedLink = useLink ? link : link.href;
|
|
213
|
-
let promise = adapter.findHasMany(store, snapshot, relatedLink, relationship);
|
|
214
|
-
let label = `DS: Handle Adapter#findHasMany of '${internalModel.modelName}' : '${relationship.type}'`;
|
|
215
|
-
|
|
216
|
-
promise = guardDestroyedStore(promise, store, label);
|
|
217
|
-
promise = promise.then(
|
|
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
|
-
|
|
237
|
-
assert(
|
|
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`,
|
|
239
|
-
payloadIsNotBlank(adapterPayload)
|
|
240
|
-
);
|
|
241
|
-
let serializer = store.serializerFor(relationship.type);
|
|
242
|
-
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findHasMany');
|
|
243
|
-
|
|
244
|
-
assert(
|
|
245
|
-
`fetched the hasMany relationship '${relationship.name}' for ${internalModel.modelName}:${internalModel.id} with link '${link}', but no data member is present in the response. If no data exists, the response should set { data: [] }`,
|
|
246
|
-
'data' in payload && Array.isArray(payload.data)
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
payload = syncRelationshipDataFromLink(store, payload, internalModel, relationship);
|
|
250
|
-
|
|
251
|
-
let internalModelArray = store._push(payload);
|
|
252
|
-
return internalModelArray;
|
|
253
|
-
},
|
|
254
|
-
null,
|
|
255
|
-
`DS: Extract payload of '${internalModel.modelName}' : hasMany '${relationship.type}'`
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
if (DEPRECATE_RSVP_PROMISE) {
|
|
259
|
-
promise = _guard(promise, _bind(_objectIsAlive, internalModel));
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return promise;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
export function _findBelongsTo(adapter, store, internalModel, link, relationship, options) {
|
|
266
|
-
let snapshot = internalModel.createSnapshot(options);
|
|
267
|
-
let modelClass = store.modelFor(relationship.type);
|
|
268
|
-
let useLink = !link || typeof link === 'string';
|
|
269
|
-
let relatedLink = useLink ? link : link.href;
|
|
270
|
-
let promise = adapter.findBelongsTo(store, snapshot, relatedLink, relationship);
|
|
271
|
-
let label = `DS: Handle Adapter#findBelongsTo of ${internalModel.modelName} : ${relationship.type}`;
|
|
272
|
-
|
|
273
|
-
promise = guardDestroyedStore(promise, store, label);
|
|
274
|
-
promise = _guard(promise, _bind(_objectIsAlive, internalModel));
|
|
275
|
-
|
|
276
|
-
promise = promise.then(
|
|
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
|
-
|
|
296
|
-
let serializer = store.serializerFor(relationship.type);
|
|
297
|
-
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo');
|
|
298
|
-
|
|
299
|
-
assert(
|
|
300
|
-
`fetched the belongsTo relationship '${relationship.name}' for ${internalModel.modelName}:${internalModel.id} with link '${link}', but no data member is present in the response. If no data exists, the response should set { data: null }`,
|
|
301
|
-
'data' in payload &&
|
|
302
|
-
(payload.data === null || (typeof payload.data === 'object' && !Array.isArray(payload.data)))
|
|
303
|
-
);
|
|
304
|
-
|
|
305
|
-
if (!payload.data && !payload.links && !payload.meta) {
|
|
306
|
-
return null;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
payload = syncRelationshipDataFromLink(store, payload, internalModel, relationship);
|
|
310
|
-
|
|
311
|
-
return store._push(payload);
|
|
312
|
-
},
|
|
313
|
-
null,
|
|
314
|
-
`DS: Extract payload of ${internalModel.modelName} : ${relationship.type}`
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
if (DEPRECATE_RSVP_PROMISE) {
|
|
318
|
-
promise = _guard(promise, _bind(_objectIsAlive, internalModel));
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return promise;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
export function _findAll(adapter, store, modelName, options) {
|
|
325
|
-
let modelClass = store.modelFor(modelName); // adapter.findAll depends on the class
|
|
326
|
-
let recordArray = store.peekAll(modelName);
|
|
327
|
-
let snapshotArray = recordArray._createSnapshot(options);
|
|
328
|
-
let promise = Promise.resolve().then(() => adapter.findAll(store, modelClass, null, snapshotArray));
|
|
329
|
-
let label = 'DS: Handle Adapter#findAll of ' + modelClass;
|
|
330
|
-
|
|
331
|
-
promise = guardDestroyedStore(promise, store, label);
|
|
332
|
-
|
|
333
|
-
return promise.then(
|
|
334
|
-
(adapterPayload) => {
|
|
335
|
-
assert(
|
|
336
|
-
`You made a 'findAll' request for '${modelName}' records, but the adapter's response did not have any data`,
|
|
337
|
-
payloadIsNotBlank(adapterPayload)
|
|
338
|
-
);
|
|
339
|
-
let serializer = store.serializerFor(modelName);
|
|
340
|
-
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findAll');
|
|
341
|
-
|
|
342
|
-
store._push(payload);
|
|
343
|
-
store._didUpdateAll(modelName);
|
|
344
|
-
|
|
345
|
-
return recordArray;
|
|
346
|
-
},
|
|
347
|
-
null,
|
|
348
|
-
'DS: Extract payload of findAll ${modelName}'
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
export function _query(adapter, store, modelName, query, recordArray, options) {
|
|
353
|
-
let modelClass = store.modelFor(modelName); // adapter.query needs the class
|
|
354
|
-
|
|
355
|
-
recordArray = recordArray || store.recordArrayManager.createAdapterPopulatedRecordArray(modelName, query);
|
|
356
|
-
let promise = Promise.resolve().then(() => adapter.query(store, modelClass, query, recordArray, options));
|
|
357
|
-
|
|
358
|
-
let label = `DS: Handle Adapter#query of ${modelName}`;
|
|
359
|
-
promise = guardDestroyedStore(promise, store, label);
|
|
360
|
-
|
|
361
|
-
return promise.then(
|
|
362
|
-
(adapterPayload) => {
|
|
363
|
-
let serializer = store.serializerFor(modelName);
|
|
364
|
-
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'query');
|
|
365
|
-
let internalModels = store._push(payload);
|
|
366
|
-
|
|
367
|
-
assert(
|
|
368
|
-
'The response to store.query is expected to be an array but it was a single record. Please wrap your response in an array or use `store.queryRecord` to query for a single record.',
|
|
369
|
-
Array.isArray(internalModels)
|
|
370
|
-
);
|
|
371
|
-
let identifiers = internalModels.map((im) => im.identifier);
|
|
372
|
-
if (recordArray) {
|
|
373
|
-
recordArray._setIdentifiers(identifiers, payload);
|
|
374
|
-
} else {
|
|
375
|
-
recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray(
|
|
376
|
-
modelName,
|
|
377
|
-
query,
|
|
378
|
-
identifiers,
|
|
379
|
-
payload
|
|
380
|
-
);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return recordArray;
|
|
384
|
-
},
|
|
385
|
-
null,
|
|
386
|
-
`DS: Extract payload of query ${modelName}`
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
export function _queryRecord(adapter, store, modelName, query, options) {
|
|
391
|
-
let modelClass = store.modelFor(modelName); // adapter.queryRecord needs the class
|
|
392
|
-
let promise = Promise.resolve().then(() => adapter.queryRecord(store, modelClass, query, options));
|
|
393
|
-
|
|
394
|
-
let label = `DS: Handle Adapter#queryRecord of ${modelName}`;
|
|
395
|
-
promise = guardDestroyedStore(promise, store, label);
|
|
396
|
-
|
|
397
|
-
return promise.then(
|
|
398
|
-
(adapterPayload) => {
|
|
399
|
-
let serializer = store.serializerFor(modelName);
|
|
400
|
-
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'queryRecord');
|
|
401
|
-
|
|
402
|
-
assert(
|
|
403
|
-
`Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array.`,
|
|
404
|
-
!Array.isArray(payload.data)
|
|
405
|
-
);
|
|
406
|
-
|
|
407
|
-
return store._push(payload);
|
|
408
|
-
},
|
|
409
|
-
null,
|
|
410
|
-
`DS: Extract payload of queryRecord ${modelName}`
|
|
411
|
-
);
|
|
412
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type EmberObject from '@ember/object';
|
|
2
|
-
|
|
3
|
-
import type { Errors } from '@ember-data/model/-private';
|
|
4
|
-
|
|
5
|
-
import type CoreStore from '../system/core-store';
|
|
6
|
-
import type InternalModel from '../system/model/internal-model';
|
|
7
|
-
import type { JsonApiValidationError } from './record-data-json-api';
|
|
8
|
-
import type { AttributeSchema, RelationshipSchema, RelationshipsSchema } from './record-data-schemas';
|
|
9
|
-
|
|
10
|
-
// Placeholder until model.js is typed
|
|
11
|
-
export interface DSModel extends EmberObject {
|
|
12
|
-
constructor: DSModelSchema;
|
|
13
|
-
store: CoreStore;
|
|
14
|
-
errors: Errors;
|
|
15
|
-
_internalModel: InternalModel;
|
|
16
|
-
toString(): string;
|
|
17
|
-
save(): Promise<DSModel>;
|
|
18
|
-
eachRelationship<T>(callback: (this: T, key: string, meta: RelationshipSchema) => void, binding?: T): void;
|
|
19
|
-
eachAttribute<T>(callback: (this: T, key: string, meta: AttributeSchema) => void, binding?: T): void;
|
|
20
|
-
invalidErrorsChanged(errors: JsonApiValidationError[]): void;
|
|
21
|
-
[key: string]: unknown;
|
|
22
|
-
isDeleted: boolean;
|
|
23
|
-
deleteRecord(): void;
|
|
24
|
-
unloadRecord(): void;
|
|
25
|
-
_notifyProperties(keys: string[]): void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Implemented by both ShimModelClass and DSModel
|
|
29
|
-
export interface ModelSchema {
|
|
30
|
-
modelName: string;
|
|
31
|
-
fields: Map<string, 'attribute' | 'belongsTo' | 'hasMany'>;
|
|
32
|
-
attributes: Map<string, AttributeSchema>;
|
|
33
|
-
relationshipsByName: Map<string, RelationshipSchema>;
|
|
34
|
-
eachAttribute<T>(callback: (this: T, key: string, attribute: AttributeSchema) => void, binding?: T): void;
|
|
35
|
-
eachRelationship<T>(callback: (this: T, key: string, relationship: RelationshipSchema) => void, binding?: T): void;
|
|
36
|
-
eachTransformedAttribute<T>(
|
|
37
|
-
callback: (this: T, key: string, relationship: RelationshipSchema) => void,
|
|
38
|
-
binding?: T
|
|
39
|
-
): void;
|
|
40
|
-
toString(): string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// This is the static side of DSModel should become DSModel
|
|
44
|
-
// once we can type it.
|
|
45
|
-
export interface DSModelSchema extends ModelSchema {
|
|
46
|
-
isModel: true;
|
|
47
|
-
relationshipsObject: RelationshipsSchema;
|
|
48
|
-
extend(...mixins: unknown[]): DSModelSchema;
|
|
49
|
-
reopenClass(...mixins: unknown[]): void;
|
|
50
|
-
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import type { Value as JSONValue } from 'json-typescript';
|
|
2
|
-
|
|
3
|
-
import type { Dict } from './utils';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
@module @ember-data/store
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export type Meta = Dict<JSONValue>;
|
|
10
|
-
export type LinkObject = { href: string; meta?: Dict<JSONValue> };
|
|
11
|
-
export type Link = string | LinkObject;
|
|
12
|
-
export interface Links {
|
|
13
|
-
related?: Link;
|
|
14
|
-
self?: Link;
|
|
15
|
-
}
|
|
16
|
-
export interface PaginationLinks extends Links {
|
|
17
|
-
first?: Link | null;
|
|
18
|
-
last?: Link | null;
|
|
19
|
-
prev?: Link | null;
|
|
20
|
-
next?: Link | null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Serves as a reference to a `Resource` but does not contain
|
|
25
|
-
* any data itself.
|
|
26
|
-
*
|
|
27
|
-
* Used to establish relationship linkages between `Resources` and
|
|
28
|
-
* to address data that may not be available synchronously.
|
|
29
|
-
*
|
|
30
|
-
* [JSON:API Spec](https://jsonapi.org/format/#document-resource-identifier-objects)
|
|
31
|
-
* @internal
|
|
32
|
-
*/
|
|
33
|
-
export interface ExistingResourceIdentifierObject {
|
|
34
|
-
id: string;
|
|
35
|
-
type: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* While not officially part of the `JSON:API` spec,
|
|
39
|
-
* `ember-data` allows the use of `lid` as a local
|
|
40
|
-
* identifier for a `Resource`.
|
|
41
|
-
*
|
|
42
|
-
* @recommended It is best to include the lid used when creating
|
|
43
|
-
* a new resource if this is the response to a new resource creation,
|
|
44
|
-
* also recommended if this resource type uses secondary indexes.
|
|
45
|
-
*
|
|
46
|
-
* Once a `ResourceIdentifierObject` has been seen by the cache, `lid`
|
|
47
|
-
* should always be present. Only when inbound from the an `API` response
|
|
48
|
-
* is `lid` considered optional.
|
|
49
|
-
*
|
|
50
|
-
* [Identifiers RFC](https://github.com/emberjs/rfcs/blob/master/text/0403-ember-data-identifiers.md#ember-data--identifiers)
|
|
51
|
-
* @internal
|
|
52
|
-
*/
|
|
53
|
-
lid?: string;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* While valid in the `JSON:API` spec,
|
|
57
|
-
* `ember-data` ignores `meta` on `ResourceIdentifierObjects`
|
|
58
|
-
*
|
|
59
|
-
* @ignored this property goes un-utilized and will be lost
|
|
60
|
-
* @internal
|
|
61
|
-
*/
|
|
62
|
-
meta?: Meta;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Serves as a reference to a resource created on the client
|
|
67
|
-
* but not yet persisted.
|
|
68
|
-
*
|
|
69
|
-
* @internal
|
|
70
|
-
*/
|
|
71
|
-
export interface NewResourceIdentifierObject {
|
|
72
|
-
/**
|
|
73
|
-
* Resources newly created on the client _may_
|
|
74
|
-
* not have an `id` available to them prior
|
|
75
|
-
* to completion of their first successful `save`.
|
|
76
|
-
*
|
|
77
|
-
* `id` will be `null` in this case.
|
|
78
|
-
*
|
|
79
|
-
* @internal
|
|
80
|
-
*/
|
|
81
|
-
id: string | null;
|
|
82
|
-
type: string;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Resources newly created on the client _will always_
|
|
86
|
-
* have an `lid` assigned immediately and available.
|
|
87
|
-
* @internal
|
|
88
|
-
*/
|
|
89
|
-
lid: string;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export interface ResourceIdentifier {
|
|
93
|
-
lid: string;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export type ResourceIdentifierObject =
|
|
97
|
-
| ResourceIdentifier
|
|
98
|
-
| ExistingResourceIdentifierObject
|
|
99
|
-
| NewResourceIdentifierObject;
|
|
100
|
-
|
|
101
|
-
// TODO disallow NewResource, make narrowable
|
|
102
|
-
export interface SingleResourceRelationship {
|
|
103
|
-
data?: ResourceIdentifierObject | null;
|
|
104
|
-
meta?: Dict<JSONValue>;
|
|
105
|
-
links?: Links;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface CollectionResourceRelationship {
|
|
109
|
-
data?: ResourceIdentifierObject[];
|
|
110
|
-
meta?: Dict<JSONValue>;
|
|
111
|
-
links?: PaginationLinks;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Contains the data for an existing resource in JSON:API format
|
|
116
|
-
* @internal
|
|
117
|
-
*/
|
|
118
|
-
export interface ExistingResourceObject extends ExistingResourceIdentifierObject {
|
|
119
|
-
meta?: Dict<JSONValue>;
|
|
120
|
-
attributes?: Dict<JSONValue>;
|
|
121
|
-
relationships?: Dict<SingleResourceRelationship | CollectionResourceRelationship>;
|
|
122
|
-
links?: Links;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
interface Document {
|
|
126
|
-
meta?: Dict<JSONValue>;
|
|
127
|
-
included?: ExistingResourceObject[];
|
|
128
|
-
jsonapi?: Dict<JSONValue>;
|
|
129
|
-
links?: Dict<string | JSONValue>;
|
|
130
|
-
errors?: JSONValue[];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export interface EmptyResourceDocument extends Document {
|
|
134
|
-
data: null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export interface SingleResourceDocument extends Document {
|
|
138
|
-
data: ExistingResourceObject;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export interface CollectionResourceDocument extends Document {
|
|
142
|
-
data: ExistingResourceObject[];
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export type JsonApiDocument = EmptyResourceDocument | SingleResourceDocument | CollectionResourceDocument;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { Dict } from '@ember-data/store/-private/ts-interfaces/utils';
|
|
2
|
-
|
|
3
|
-
import type { RecordIdentifier } from './identifier';
|
|
4
|
-
|
|
5
|
-
export interface Operation {
|
|
6
|
-
op: string;
|
|
7
|
-
options: Dict<unknown> | undefined;
|
|
8
|
-
recordIdentifier: RecordIdentifier;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface FindRecordQuery extends Operation {
|
|
12
|
-
op: 'findRecord';
|
|
13
|
-
recordIdentifier: RecordIdentifier;
|
|
14
|
-
options: any;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface SaveRecordMutation extends Operation {
|
|
18
|
-
op: 'saveRecord';
|
|
19
|
-
recordIdentifier: RecordIdentifier;
|
|
20
|
-
options: any;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface Request {
|
|
24
|
-
data: Operation[];
|
|
25
|
-
options?: any;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export enum RequestStateEnum {
|
|
29
|
-
pending = 'pending',
|
|
30
|
-
fulfilled = 'fulfilled',
|
|
31
|
-
rejected = 'rejected',
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface RequestState {
|
|
35
|
-
state: RequestStateEnum;
|
|
36
|
-
type: 'query' | 'mutation';
|
|
37
|
-
request: Request;
|
|
38
|
-
response?: Response;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface Response {
|
|
42
|
-
// rawData: unknown;
|
|
43
|
-
data: unknown;
|
|
44
|
-
}
|