@ember-data/legacy-compat 4.12.0-alpha.11 → 4.12.0-alpha.13
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.js +1 -1
- package/addon/{fetch-manager-2716abb1.js → fetch-manager-1067c70f.js} +537 -112
- package/addon/fetch-manager-1067c70f.js.map +1 -0
- package/addon/index.js +405 -42
- package/addon/index.js.map +1 -1
- package/addon-main.js +7 -31
- package/package.json +15 -4
- package/addon/fetch-manager-2716abb1.js.map +0 -1
package/addon/index.js
CHANGED
|
@@ -1,7 +1,274 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { deprecate, assert } from '@ember/debug';
|
|
2
|
+
import { macroCondition, getOwnConfig, importSync } from '@embroider/macros';
|
|
3
|
+
import { g as guardDestroyedStore, _ as _objectIsAlive, p as payloadIsNotBlank, n as normalizeResponseHelper, c as _guard, i as iterateData, d as _bind, F as FetchManager, e as assertIdentifierHasId, a as SaveOp, S as SnapshotRecordArray } from "./fetch-manager-1067c70f";
|
|
4
|
+
function _findHasMany(adapter, store, identifier, link, relationship, options) {
|
|
5
|
+
let promise = Promise.resolve().then(() => {
|
|
6
|
+
const snapshot = store._fetchManager.createSnapshot(identifier, options);
|
|
7
|
+
let useLink = !link || typeof link === 'string';
|
|
8
|
+
let relatedLink = useLink ? link : link.href;
|
|
9
|
+
return adapter.findHasMany(store, snapshot, relatedLink, relationship);
|
|
10
|
+
});
|
|
11
|
+
promise = guardDestroyedStore(promise, store);
|
|
12
|
+
promise = promise.then(adapterPayload => {
|
|
13
|
+
const record = store._instanceCache.getRecord(identifier);
|
|
14
|
+
if (!_objectIsAlive(record)) {
|
|
15
|
+
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
|
|
16
|
+
deprecate(`A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`, false, {
|
|
17
|
+
id: 'ember-data:rsvp-unresolved-async',
|
|
18
|
+
until: '5.0',
|
|
19
|
+
for: '@ember-data/store',
|
|
20
|
+
since: {
|
|
21
|
+
available: '4.5',
|
|
22
|
+
enabled: '4.5'
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
assert(`You made a 'findHasMany' request for a ${identifier.type}'s '${relationship.key}' relationship, using link '${link}' , but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload));
|
|
28
|
+
const modelClass = store.modelFor(relationship.type);
|
|
29
|
+
let serializer = store.serializerFor(relationship.type);
|
|
30
|
+
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findHasMany');
|
|
31
|
+
assert(`fetched the hasMany relationship '${relationship.name}' for ${identifier.type}:${identifier.id} with link '${link}', but no data member is present in the response. If no data exists, the response should set { data: [] }`, 'data' in payload && Array.isArray(payload.data));
|
|
32
|
+
payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
|
|
33
|
+
return store._push(payload, true);
|
|
34
|
+
}, null, `DS: Extract payload of '${identifier.type}' : hasMany '${relationship.type}'`);
|
|
35
|
+
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
|
|
36
|
+
const record = store._instanceCache.getRecord(identifier);
|
|
37
|
+
promise = _guard(promise, _bind(_objectIsAlive, record));
|
|
38
|
+
}
|
|
39
|
+
return promise;
|
|
40
|
+
}
|
|
41
|
+
function _findBelongsTo(store, identifier, link, relationship, options) {
|
|
42
|
+
let promise = Promise.resolve().then(() => {
|
|
43
|
+
let adapter = store.adapterFor(identifier.type);
|
|
44
|
+
assert(`You tried to load a belongsTo relationship but you have no adapter (for ${identifier.type})`, adapter);
|
|
45
|
+
assert(`You tried to load a belongsTo relationship from a specified 'link' in the original payload but your adapter does not implement 'findBelongsTo'`, typeof adapter.findBelongsTo === 'function');
|
|
46
|
+
let snapshot = store._fetchManager.createSnapshot(identifier, options);
|
|
47
|
+
let useLink = !link || typeof link === 'string';
|
|
48
|
+
let relatedLink = useLink ? link : link.href;
|
|
49
|
+
return adapter.findBelongsTo(store, snapshot, relatedLink, relationship);
|
|
50
|
+
});
|
|
51
|
+
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
|
|
52
|
+
const record = store._instanceCache.getRecord(identifier);
|
|
53
|
+
promise = guardDestroyedStore(promise, store);
|
|
54
|
+
promise = _guard(promise, _bind(_objectIsAlive, record));
|
|
55
|
+
}
|
|
56
|
+
promise = promise.then(adapterPayload => {
|
|
57
|
+
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RSVP_PROMISE)) {
|
|
58
|
+
const record = store._instanceCache.getRecord(identifier);
|
|
59
|
+
if (!_objectIsAlive(record)) {
|
|
60
|
+
deprecate(`A Promise for fetching ${relationship.type} did not resolve by the time your model was destroyed. This will error in a future release.`, false, {
|
|
61
|
+
id: 'ember-data:rsvp-unresolved-async',
|
|
62
|
+
until: '5.0',
|
|
63
|
+
for: '@ember-data/store',
|
|
64
|
+
since: {
|
|
65
|
+
available: '4.5',
|
|
66
|
+
enabled: '4.5'
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
let modelClass = store.modelFor(relationship.type);
|
|
72
|
+
let serializer = store.serializerFor(relationship.type);
|
|
73
|
+
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo');
|
|
74
|
+
assert(`fetched the belongsTo relationship '${relationship.name}' for ${identifier.type}:${identifier.id} with link '${link}', but no data member is present in the response. If no data exists, the response should set { data: null }`, 'data' in payload && (payload.data === null || typeof payload.data === 'object' && !Array.isArray(payload.data)));
|
|
75
|
+
if (!payload.data && !payload.links && !payload.meta) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
|
|
79
|
+
return store._push(payload, true);
|
|
80
|
+
}, null, `DS: Extract payload of ${identifier.type} : ${relationship.type}`);
|
|
81
|
+
return promise;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// sync
|
|
85
|
+
// iterate over records in payload.data
|
|
86
|
+
// for each record
|
|
87
|
+
// assert that record.relationships[inverse] is either undefined (so we can fix it)
|
|
88
|
+
// or provide a data: {id, type} that matches the record that requested it
|
|
89
|
+
// return the relationship data for the parent
|
|
90
|
+
function syncRelationshipDataFromLink(store, payload, parentIdentifier, relationship) {
|
|
91
|
+
// ensure the right hand side (incoming payload) points to the parent record that
|
|
92
|
+
// requested this relationship
|
|
93
|
+
let relationshipData = payload.data ? iterateData(payload.data, (data, index) => {
|
|
94
|
+
const {
|
|
95
|
+
id,
|
|
96
|
+
type
|
|
97
|
+
} = data;
|
|
98
|
+
ensureRelationshipIsSetToParent(data, parentIdentifier, store, relationship, index);
|
|
99
|
+
return {
|
|
100
|
+
id,
|
|
101
|
+
type
|
|
102
|
+
};
|
|
103
|
+
}) : null;
|
|
104
|
+
const relatedDataHash = {};
|
|
105
|
+
if ('meta' in payload) {
|
|
106
|
+
relatedDataHash.meta = payload.meta;
|
|
107
|
+
}
|
|
108
|
+
if ('links' in payload) {
|
|
109
|
+
relatedDataHash.links = payload.links;
|
|
110
|
+
}
|
|
111
|
+
if ('data' in payload) {
|
|
112
|
+
relatedDataHash.data = relationshipData;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// now, push the left hand side (the parent record) to ensure things are in sync, since
|
|
116
|
+
// the payload will be pushed with store._push
|
|
117
|
+
const parentPayload = {
|
|
118
|
+
id: parentIdentifier.id,
|
|
119
|
+
type: parentIdentifier.type,
|
|
120
|
+
relationships: {
|
|
121
|
+
[relationship.key]: relatedDataHash
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
if (!Array.isArray(payload.included)) {
|
|
125
|
+
payload.included = [];
|
|
126
|
+
}
|
|
127
|
+
payload.included.push(parentPayload);
|
|
128
|
+
return payload;
|
|
129
|
+
}
|
|
130
|
+
function ensureRelationshipIsSetToParent(payload, parentIdentifier, store, parentRelationship, index) {
|
|
131
|
+
let {
|
|
132
|
+
id,
|
|
133
|
+
type
|
|
134
|
+
} = payload;
|
|
135
|
+
if (!payload.relationships) {
|
|
136
|
+
payload.relationships = {};
|
|
137
|
+
}
|
|
138
|
+
let {
|
|
139
|
+
relationships
|
|
140
|
+
} = payload;
|
|
141
|
+
let inverse = getInverse(store, parentIdentifier, parentRelationship, type);
|
|
142
|
+
if (inverse) {
|
|
143
|
+
let {
|
|
144
|
+
inverseKey,
|
|
145
|
+
kind
|
|
146
|
+
} = inverse;
|
|
147
|
+
let relationshipData = relationships[inverseKey] && relationships[inverseKey].data;
|
|
148
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
149
|
+
if (typeof relationshipData !== 'undefined' && !relationshipDataPointsToParent(relationshipData, parentIdentifier)) {
|
|
150
|
+
let inspect = function inspect(thing) {
|
|
151
|
+
return `'${JSON.stringify(thing)}'`;
|
|
152
|
+
};
|
|
153
|
+
let quotedType = inspect(type);
|
|
154
|
+
let quotedInverse = inspect(inverseKey);
|
|
155
|
+
let expected = inspect({
|
|
156
|
+
id: parentIdentifier.id,
|
|
157
|
+
type: parentIdentifier.type
|
|
158
|
+
});
|
|
159
|
+
let expectedModel = `${parentIdentifier.type}:${parentIdentifier.id}`;
|
|
160
|
+
let got = inspect(relationshipData);
|
|
161
|
+
let prefix = typeof index === 'number' ? `data[${index}]` : `data`;
|
|
162
|
+
let path = `${prefix}.relationships.${inverseKey}.data`;
|
|
163
|
+
let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null;
|
|
164
|
+
let relationshipFetched = `${expectedModel}.${parentRelationship.kind}("${parentRelationship.name}")`;
|
|
165
|
+
let includedRecord = `<${type}:${id}>`;
|
|
166
|
+
let message = [`Encountered mismatched relationship: Ember Data expected ${path} in the payload from ${relationshipFetched} to include ${expected} but got ${got} instead.\n`, `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.`, `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 ${parentIdentifier.type} record instead.`, `Ember Data has corrected the ${includedRecord} record's ${quotedInverse} relationship to ${expectedModel} so that ${relationshipFetched} will include ${includedRecord}.`, `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.`].join('\n');
|
|
167
|
+
assert(message);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (kind !== 'hasMany' || typeof relationshipData !== 'undefined') {
|
|
171
|
+
relationships[inverseKey] = relationships[inverseKey] || {};
|
|
172
|
+
relationships[inverseKey].data = fixRelationshipData(relationshipData, kind, parentIdentifier);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function metaIsRelationshipDefinition(meta) {
|
|
177
|
+
return typeof meta._inverseKey === 'function';
|
|
178
|
+
}
|
|
179
|
+
function inverseForRelationship(store, identifier, key) {
|
|
180
|
+
const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor(identifier)[key];
|
|
181
|
+
if (!definition) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
if (macroCondition(getOwnConfig().deprecations.DEPRECATE_RELATIONSHIPS_WITHOUT_INVERSE)) {
|
|
185
|
+
if (metaIsRelationshipDefinition(definition)) {
|
|
186
|
+
const modelClass = store.modelFor(identifier.type);
|
|
187
|
+
return definition._inverseKey(store, modelClass);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
assert(`Expected the relationship defintion to specify the inverse type or null.`, definition.options?.inverse === null || typeof definition.options?.inverse === 'string' && definition.options.inverse.length > 0);
|
|
191
|
+
return definition.options.inverse;
|
|
192
|
+
}
|
|
193
|
+
function getInverse(store, parentIdentifier, parentRelationship, type) {
|
|
194
|
+
let {
|
|
195
|
+
name: lhs_relationshipName
|
|
196
|
+
} = parentRelationship;
|
|
197
|
+
let {
|
|
198
|
+
type: parentType
|
|
199
|
+
} = parentIdentifier;
|
|
200
|
+
let inverseKey = inverseForRelationship(store, {
|
|
201
|
+
type: parentType
|
|
202
|
+
}, lhs_relationshipName);
|
|
203
|
+
if (inverseKey) {
|
|
204
|
+
const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor({
|
|
205
|
+
type
|
|
206
|
+
});
|
|
207
|
+
let {
|
|
208
|
+
kind
|
|
209
|
+
} = definition[inverseKey];
|
|
210
|
+
return {
|
|
211
|
+
inverseKey,
|
|
212
|
+
kind
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function relationshipDataPointsToParent(relationshipData, identifier) {
|
|
217
|
+
if (relationshipData === null) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
if (Array.isArray(relationshipData)) {
|
|
221
|
+
if (relationshipData.length === 0) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
for (let i = 0; i < relationshipData.length; i++) {
|
|
225
|
+
let entry = relationshipData[i];
|
|
226
|
+
if (validateRelationshipEntry(entry, identifier)) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
return validateRelationshipEntry(relationshipData, identifier);
|
|
232
|
+
}
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
function fixRelationshipData(relationshipData, relationshipKind, {
|
|
236
|
+
id,
|
|
237
|
+
type
|
|
238
|
+
}) {
|
|
239
|
+
let parentRelationshipData = {
|
|
240
|
+
id,
|
|
241
|
+
type
|
|
242
|
+
};
|
|
243
|
+
let payload;
|
|
244
|
+
if (relationshipKind === 'hasMany') {
|
|
245
|
+
payload = relationshipData || [];
|
|
246
|
+
if (relationshipData) {
|
|
247
|
+
// these arrays could be massive so this is better than filter
|
|
248
|
+
// Note: this is potentially problematic if type/id are not in the
|
|
249
|
+
// same state of normalization.
|
|
250
|
+
let found = relationshipData.find(v => {
|
|
251
|
+
return v.type === parentRelationshipData.type && v.id === parentRelationshipData.id;
|
|
252
|
+
});
|
|
253
|
+
if (!found) {
|
|
254
|
+
payload.push(parentRelationshipData);
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
payload.push(parentRelationshipData);
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
payload = relationshipData || {};
|
|
261
|
+
Object.assign(payload, parentRelationshipData);
|
|
262
|
+
}
|
|
263
|
+
return payload;
|
|
264
|
+
}
|
|
265
|
+
function validateRelationshipEntry({
|
|
266
|
+
id
|
|
267
|
+
}, {
|
|
268
|
+
id: parentModelID
|
|
269
|
+
}) {
|
|
270
|
+
return id && id.toString() === parentModelID;
|
|
271
|
+
}
|
|
5
272
|
const LegacyNetworkHandler = {
|
|
6
273
|
request(context, next) {
|
|
7
274
|
// if we are not a legacy request, move on
|
|
@@ -15,25 +282,100 @@ const LegacyNetworkHandler = {
|
|
|
15
282
|
store._fetchManager = new FetchManager(store);
|
|
16
283
|
}
|
|
17
284
|
switch (context.request.op) {
|
|
18
|
-
case 'updateRecord':
|
|
19
|
-
return saveRecord(context);
|
|
20
|
-
case 'deleteRecord':
|
|
21
|
-
return saveRecord(context);
|
|
22
|
-
case 'createRecord':
|
|
23
|
-
return saveRecord(context);
|
|
24
285
|
case 'findRecord':
|
|
25
286
|
return findRecord(context);
|
|
26
287
|
case 'findAll':
|
|
27
288
|
return findAll(context);
|
|
28
|
-
case 'queryRecord':
|
|
29
|
-
return queryRecord(context);
|
|
30
289
|
case 'query':
|
|
31
290
|
return query(context);
|
|
291
|
+
case 'queryRecord':
|
|
292
|
+
return queryRecord(context);
|
|
293
|
+
case 'findBelongsTo':
|
|
294
|
+
return findBelongsTo(context);
|
|
295
|
+
case 'findHasMany':
|
|
296
|
+
return findHasMany(context);
|
|
297
|
+
case 'updateRecord':
|
|
298
|
+
return saveRecord(context);
|
|
299
|
+
case 'createRecord':
|
|
300
|
+
return saveRecord(context);
|
|
301
|
+
case 'deleteRecord':
|
|
302
|
+
return saveRecord(context);
|
|
32
303
|
default:
|
|
33
304
|
return next(context.request);
|
|
34
305
|
}
|
|
35
306
|
}
|
|
36
307
|
};
|
|
308
|
+
function findBelongsTo(context) {
|
|
309
|
+
const {
|
|
310
|
+
store,
|
|
311
|
+
data,
|
|
312
|
+
records: identifiers
|
|
313
|
+
} = context.request;
|
|
314
|
+
const {
|
|
315
|
+
options,
|
|
316
|
+
record,
|
|
317
|
+
links,
|
|
318
|
+
useLink,
|
|
319
|
+
field
|
|
320
|
+
} = data;
|
|
321
|
+
const identifier = identifiers?.[0];
|
|
322
|
+
|
|
323
|
+
// short circuit if we are already loading
|
|
324
|
+
let pendingRequest = identifier && store._fetchManager.getPendingFetch(identifier, options);
|
|
325
|
+
if (pendingRequest) {
|
|
326
|
+
return pendingRequest;
|
|
327
|
+
}
|
|
328
|
+
if (useLink) {
|
|
329
|
+
return _findBelongsTo(store, record, links.related, field, options);
|
|
330
|
+
}
|
|
331
|
+
assert(`Expected an identifier`, Array.isArray(identifiers) && identifiers.length === 1);
|
|
332
|
+
const manager = store._fetchManager;
|
|
333
|
+
assertIdentifierHasId(identifier);
|
|
334
|
+
return options.reload ? manager.scheduleFetch(identifier, options, context.request) : manager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
|
|
335
|
+
}
|
|
336
|
+
function findHasMany(context) {
|
|
337
|
+
const {
|
|
338
|
+
store,
|
|
339
|
+
data,
|
|
340
|
+
records: identifiers
|
|
341
|
+
} = context.request;
|
|
342
|
+
const {
|
|
343
|
+
options,
|
|
344
|
+
record,
|
|
345
|
+
links,
|
|
346
|
+
useLink,
|
|
347
|
+
field
|
|
348
|
+
} = data;
|
|
349
|
+
|
|
350
|
+
// link case
|
|
351
|
+
if (useLink) {
|
|
352
|
+
const adapter = store.adapterFor(record.type);
|
|
353
|
+
/*
|
|
354
|
+
If a relationship was originally populated by the adapter as a link
|
|
355
|
+
(as opposed to a list of IDs), this method is called when the
|
|
356
|
+
relationship is fetched.
|
|
357
|
+
The link (which is usually a URL) is passed through unchanged, so the
|
|
358
|
+
adapter can make whatever request it wants.
|
|
359
|
+
The usual use-case is for the server to register a URL as a link, and
|
|
360
|
+
then use that URL in the future to make a request for the relationship.
|
|
361
|
+
*/
|
|
362
|
+
assert(`You tried to load a hasMany relationship but you have no adapter (for ${record.type})`, adapter);
|
|
363
|
+
assert(`You tried to load a hasMany relationship from a specified 'link' in the original payload but your adapter does not implement 'findHasMany'`, typeof adapter.findHasMany === 'function');
|
|
364
|
+
return _findHasMany(adapter, store, record, links.related, field, options);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// identifiers case
|
|
368
|
+
|
|
369
|
+
const fetches = new Array(identifiers.length);
|
|
370
|
+
const manager = store._fetchManager;
|
|
371
|
+
for (let i = 0; i < identifiers.length; i++) {
|
|
372
|
+
let identifier = identifiers[i];
|
|
373
|
+
// TODO we probably can be lenient here and return from cache for the isNew case
|
|
374
|
+
assertIdentifierHasId(identifier);
|
|
375
|
+
fetches[i] = options.reload ? manager.scheduleFetch(identifier, options, context.request) : manager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
|
|
376
|
+
}
|
|
377
|
+
return Promise.all(fetches);
|
|
378
|
+
}
|
|
37
379
|
function saveRecord(context) {
|
|
38
380
|
const {
|
|
39
381
|
store,
|
|
@@ -87,7 +429,7 @@ function saveRecord(context) {
|
|
|
87
429
|
store._push({
|
|
88
430
|
data: null,
|
|
89
431
|
included: payload.included
|
|
90
|
-
});
|
|
432
|
+
}, true);
|
|
91
433
|
}
|
|
92
434
|
});
|
|
93
435
|
return store.peekRecord(identifier);
|
|
@@ -172,29 +514,43 @@ function findRecord(context) {
|
|
|
172
514
|
|
|
173
515
|
// if not loaded start loading
|
|
174
516
|
if (!store._instanceCache.recordIsLoaded(identifier)) {
|
|
175
|
-
promise = store._fetchManager.fetchDataIfNeededForIdentifier(identifier, options);
|
|
517
|
+
promise = store._fetchManager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
|
|
176
518
|
|
|
177
519
|
// Refetch if the reload option is passed
|
|
178
520
|
} else if (options.reload) {
|
|
179
521
|
assertIdentifierHasId(identifier);
|
|
180
|
-
promise = store._fetchManager.scheduleFetch(identifier, options);
|
|
522
|
+
promise = store._fetchManager.scheduleFetch(identifier, options, context.request);
|
|
181
523
|
} else {
|
|
182
524
|
let snapshot = null;
|
|
183
525
|
let adapter = store.adapterFor(identifier.type);
|
|
184
526
|
|
|
185
527
|
// Refetch the record if the adapter thinks the record is stale
|
|
186
|
-
if (typeof options.reload === 'undefined' && adapter.shouldReloadRecord && adapter.shouldReloadRecord(store, snapshot = store.
|
|
528
|
+
if (typeof options.reload === 'undefined' && adapter.shouldReloadRecord && adapter.shouldReloadRecord(store, snapshot = store._fetchManager.createSnapshot(identifier, options))) {
|
|
187
529
|
assertIdentifierHasId(identifier);
|
|
188
|
-
|
|
530
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
531
|
+
promise = store._fetchManager.scheduleFetch(identifier, Object.assign({}, options, {
|
|
532
|
+
reload: true
|
|
533
|
+
}), context.request);
|
|
534
|
+
} else {
|
|
535
|
+
options.reload = true;
|
|
536
|
+
promise = store._fetchManager.scheduleFetch(identifier, options, context.request);
|
|
537
|
+
}
|
|
189
538
|
} else {
|
|
190
539
|
// Trigger the background refetch if backgroundReload option is passed
|
|
191
|
-
if (options.backgroundReload !== false && (options.backgroundReload || !adapter.shouldBackgroundReloadRecord || adapter.shouldBackgroundReloadRecord(store, snapshot = snapshot || store.
|
|
540
|
+
if (options.backgroundReload !== false && (options.backgroundReload || !adapter.shouldBackgroundReloadRecord || adapter.shouldBackgroundReloadRecord(store, snapshot = snapshot || store._fetchManager.createSnapshot(identifier, options)))) {
|
|
192
541
|
assertIdentifierHasId(identifier);
|
|
193
|
-
|
|
542
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
543
|
+
void store._fetchManager.scheduleFetch(identifier, Object.assign({}, options, {
|
|
544
|
+
backgroundReload: true
|
|
545
|
+
}), context.request);
|
|
546
|
+
} else {
|
|
547
|
+
options.backgroundReload = true;
|
|
548
|
+
void store._fetchManager.scheduleFetch(identifier, options, context.request);
|
|
549
|
+
}
|
|
194
550
|
}
|
|
195
551
|
|
|
196
552
|
// Return the cached record
|
|
197
|
-
promise = resolve(identifier);
|
|
553
|
+
promise = Promise.resolve(identifier);
|
|
198
554
|
}
|
|
199
555
|
}
|
|
200
556
|
return promise.then(identifier => store.peekRecord(identifier));
|
|
@@ -219,35 +575,41 @@ function findAll(context) {
|
|
|
219
575
|
let fetch;
|
|
220
576
|
if (shouldReload) {
|
|
221
577
|
maybeRecordArray && (maybeRecordArray.isUpdating = true);
|
|
222
|
-
fetch = _findAll(adapter, store, type, snapshotArray);
|
|
578
|
+
fetch = _findAll(adapter, store, type, snapshotArray, context.request, true);
|
|
223
579
|
} else {
|
|
224
|
-
fetch = Promise
|
|
580
|
+
fetch = Promise.resolve(store.peekAll(type));
|
|
225
581
|
if (options.backgroundReload || options.backgroundReload !== false && (!adapter.shouldBackgroundReloadAll || adapter.shouldBackgroundReloadAll(store, snapshotArray))) {
|
|
226
582
|
maybeRecordArray && (maybeRecordArray.isUpdating = true);
|
|
227
|
-
void _findAll(adapter, store, type, snapshotArray);
|
|
583
|
+
void _findAll(adapter, store, type, snapshotArray, context.request, false);
|
|
228
584
|
}
|
|
229
585
|
}
|
|
230
586
|
return fetch;
|
|
231
587
|
}
|
|
232
|
-
function
|
|
233
|
-
if (Array.isArray(adapterPayload)) {
|
|
234
|
-
return true;
|
|
235
|
-
} else {
|
|
236
|
-
return Object.keys(adapterPayload || {}).length;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
function _findAll(adapter, store, type, snapshotArray) {
|
|
588
|
+
function _findAll(adapter, store, type, snapshotArray, request, isAsyncFlush) {
|
|
240
589
|
const schema = store.modelFor(type);
|
|
241
|
-
let promise = Promise
|
|
242
|
-
promise = guardDestroyedStore(promise, store
|
|
243
|
-
|
|
590
|
+
let promise = Promise.resolve().then(() => adapter.findAll(store, schema, null, snapshotArray));
|
|
591
|
+
promise = guardDestroyedStore(promise, store);
|
|
592
|
+
promise = promise.then(adapterPayload => {
|
|
244
593
|
assert(`You made a 'findAll' request for '${type}' records, but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload));
|
|
245
594
|
const serializer = store.serializerFor(type);
|
|
246
595
|
const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'findAll');
|
|
247
|
-
store._push(payload);
|
|
596
|
+
store._push(payload, isAsyncFlush);
|
|
248
597
|
snapshotArray._recordArray.isUpdating = false;
|
|
598
|
+
if (macroCondition(getOwnConfig().debug.LOG_PAYLOADS)) {
|
|
599
|
+
// eslint-disable-next-line no-console
|
|
600
|
+
console.log(`request: findAll<${type}> background reload complete`);
|
|
601
|
+
}
|
|
249
602
|
return snapshotArray._recordArray;
|
|
250
603
|
});
|
|
604
|
+
if (macroCondition(getOwnConfig().env.TESTING)) {
|
|
605
|
+
if (!request.disableTestWaiter) {
|
|
606
|
+
const {
|
|
607
|
+
waitForPromise
|
|
608
|
+
} = importSync('@ember/test-waiters');
|
|
609
|
+
promise = waitForPromise(promise);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return promise;
|
|
251
613
|
}
|
|
252
614
|
function query(context) {
|
|
253
615
|
const {
|
|
@@ -268,19 +630,19 @@ function query(context) {
|
|
|
268
630
|
type,
|
|
269
631
|
query
|
|
270
632
|
});
|
|
271
|
-
if (
|
|
633
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
272
634
|
options = Object.assign({}, options);
|
|
273
635
|
delete options._recordArray;
|
|
274
636
|
} else {
|
|
275
637
|
delete options._recordArray;
|
|
276
638
|
}
|
|
277
639
|
const schema = store.modelFor(type);
|
|
278
|
-
let promise = Promise
|
|
279
|
-
promise = guardDestroyedStore(promise, store
|
|
640
|
+
let promise = Promise.resolve().then(() => adapter.query(store, schema, query, recordArray, options));
|
|
641
|
+
promise = guardDestroyedStore(promise, store);
|
|
280
642
|
return promise.then(adapterPayload => {
|
|
281
643
|
const serializer = store.serializerFor(type);
|
|
282
644
|
const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'query');
|
|
283
|
-
const identifiers = store._push(payload);
|
|
645
|
+
const identifiers = store._push(payload, true);
|
|
284
646
|
assert('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.', Array.isArray(identifiers));
|
|
285
647
|
store.recordArrayManager.populateManagedArray(recordArray, identifiers, payload);
|
|
286
648
|
return recordArray;
|
|
@@ -303,13 +665,14 @@ function queryRecord(context) {
|
|
|
303
665
|
assert(`You tried to make a query but you have no adapter (for ${type})`, adapter);
|
|
304
666
|
assert(`You tried to make a query but your adapter does not implement 'queryRecord'`, typeof adapter.queryRecord === 'function');
|
|
305
667
|
const schema = store.modelFor(type);
|
|
306
|
-
let promise = Promise
|
|
307
|
-
promise = guardDestroyedStore(promise, store
|
|
668
|
+
let promise = Promise.resolve().then(() => adapter.queryRecord(store, schema, query, options));
|
|
669
|
+
promise = guardDestroyedStore(promise, store);
|
|
308
670
|
return promise.then(adapterPayload => {
|
|
309
671
|
const serializer = store.serializerFor(type);
|
|
310
672
|
const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'queryRecord');
|
|
311
673
|
assertSingleResourceDocument(payload);
|
|
312
|
-
|
|
674
|
+
const identifier = store._push(payload, true);
|
|
675
|
+
return identifier ? store.peekRecord(identifier) : null;
|
|
313
676
|
});
|
|
314
677
|
}
|
|
315
678
|
export { LegacyNetworkHandler };
|