@ember-data/legacy-compat 4.12.0-alpha.9 → 4.12.0-beta.10
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/LICENSE.md +1 -1
- package/addon/-private.js +1 -1
- package/addon/fetch-manager-69fdecd9.js +1024 -0
- package/addon/fetch-manager-69fdecd9.js.map +1 -0
- package/addon/index.js +477 -1645
- package/addon/index.js.map +1 -1
- package/addon-main.js +18 -15
- package/ember-data-logo-dark.svg +12 -0
- package/ember-data-logo-light.svg +12 -0
- package/package.json +28 -13
- package/addon/snapshot-record-array-a4efeb60.js +0 -169
- package/addon/snapshot-record-array-a4efeb60.js.map +0 -1
package/addon/index.js
CHANGED
|
@@ -1,1686 +1,514 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { S as SnapshotRecordArray } from "./
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { assert } from '@ember/debug';
|
|
2
|
+
import { macroCondition, getOwnConfig, importSync } from '@embroider/macros';
|
|
3
|
+
import { p as payloadIsNotBlank, n as normalizeResponseHelper, i as iterateData, F as FetchManager, c as assertIdentifierHasId, a as SaveOp, S as SnapshotRecordArray } from "./fetch-manager-69fdecd9";
|
|
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 = promise.then(adapterPayload => {
|
|
12
|
+
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));
|
|
13
|
+
const modelClass = store.modelFor(relationship.type);
|
|
14
|
+
let serializer = store.serializerFor(relationship.type);
|
|
15
|
+
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findHasMany');
|
|
16
|
+
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));
|
|
17
|
+
payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
|
|
18
|
+
return store._push(payload, true);
|
|
19
|
+
}, null, `DS: Extract payload of '${identifier.type}' : hasMany '${relationship.type}'`);
|
|
20
|
+
return promise;
|
|
21
|
+
}
|
|
22
|
+
function _findBelongsTo(store, identifier, link, relationship, options) {
|
|
23
|
+
let promise = Promise.resolve().then(() => {
|
|
24
|
+
let adapter = store.adapterFor(identifier.type);
|
|
25
|
+
assert(`You tried to load a belongsTo relationship but you have no adapter (for ${identifier.type})`, adapter);
|
|
26
|
+
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');
|
|
27
|
+
let snapshot = store._fetchManager.createSnapshot(identifier, options);
|
|
28
|
+
let useLink = !link || typeof link === 'string';
|
|
29
|
+
let relatedLink = useLink ? link : link.href;
|
|
30
|
+
return adapter.findBelongsTo(store, snapshot, relatedLink, relationship);
|
|
31
|
+
});
|
|
32
|
+
promise = promise.then(adapterPayload => {
|
|
33
|
+
let modelClass = store.modelFor(relationship.type);
|
|
34
|
+
let serializer = store.serializerFor(relationship.type);
|
|
35
|
+
let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo');
|
|
36
|
+
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)));
|
|
37
|
+
if (!payload.data && !payload.links && !payload.meta) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
payload = syncRelationshipDataFromLink(store, payload, identifier, relationship);
|
|
41
|
+
return store._push(payload, true);
|
|
42
|
+
}, null, `DS: Extract payload of ${identifier.type} : ${relationship.type}`);
|
|
43
|
+
return promise;
|
|
19
44
|
}
|
|
20
45
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
let yehuda = new Person();
|
|
45
|
-
let tom = new Person();
|
|
46
|
-
yehuda.on('poke', function(event) {
|
|
47
|
-
console.log('Yehuda says OW');
|
|
48
|
-
});
|
|
49
|
-
tom.on('poke', function(event) {
|
|
50
|
-
console.log('Tom says OW');
|
|
51
|
-
});
|
|
52
|
-
yehuda.trigger('poke');
|
|
53
|
-
tom.trigger('poke');
|
|
54
|
-
```
|
|
55
|
-
@method mixin
|
|
56
|
-
@for rsvp
|
|
57
|
-
@private
|
|
58
|
-
@param {Object} object object to extend with EventTarget methods
|
|
59
|
-
*/
|
|
60
|
-
mixin: function (object) {
|
|
61
|
-
object.on = this.on;
|
|
62
|
-
object.off = this.off;
|
|
63
|
-
object.trigger = this.trigger;
|
|
64
|
-
object._promiseCallbacks = undefined;
|
|
65
|
-
return object;
|
|
66
|
-
},
|
|
67
|
-
/**
|
|
68
|
-
Registers a callback to be executed when `eventName` is triggered
|
|
69
|
-
```javascript
|
|
70
|
-
object.on('event', function(eventInfo){
|
|
71
|
-
// handle the event
|
|
72
|
-
});
|
|
73
|
-
object.trigger('event');
|
|
74
|
-
```
|
|
75
|
-
@method on
|
|
76
|
-
@for EventTarget
|
|
77
|
-
@private
|
|
78
|
-
@param {String} eventName name of the event to listen for
|
|
79
|
-
@param {Function} callback function to be called when the event is triggered.
|
|
80
|
-
*/
|
|
81
|
-
on: function (eventName, callback) {
|
|
82
|
-
if (typeof callback !== 'function') {
|
|
83
|
-
throw new TypeError('Callback must be a function');
|
|
84
|
-
}
|
|
85
|
-
var allCallbacks = callbacksFor(this);
|
|
86
|
-
var callbacks = allCallbacks[eventName];
|
|
87
|
-
if (!callbacks) {
|
|
88
|
-
callbacks = allCallbacks[eventName] = [];
|
|
89
|
-
}
|
|
90
|
-
if (callbacks.indexOf(callback) === -1) {
|
|
91
|
-
callbacks.push(callback);
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
/**
|
|
95
|
-
You can use `off` to stop firing a particular callback for an event:
|
|
96
|
-
```javascript
|
|
97
|
-
function doStuff() { // do stuff! }
|
|
98
|
-
object.on('stuff', doStuff);
|
|
99
|
-
object.trigger('stuff'); // doStuff will be called
|
|
100
|
-
// Unregister ONLY the doStuff callback
|
|
101
|
-
object.off('stuff', doStuff);
|
|
102
|
-
object.trigger('stuff'); // doStuff will NOT be called
|
|
103
|
-
```
|
|
104
|
-
If you don't pass a `callback` argument to `off`, ALL callbacks for the
|
|
105
|
-
event will not be executed when the event fires. For example:
|
|
106
|
-
```javascript
|
|
107
|
-
let callback1 = function(){};
|
|
108
|
-
let callback2 = function(){};
|
|
109
|
-
object.on('stuff', callback1);
|
|
110
|
-
object.on('stuff', callback2);
|
|
111
|
-
object.trigger('stuff'); // callback1 and callback2 will be executed.
|
|
112
|
-
object.off('stuff');
|
|
113
|
-
object.trigger('stuff'); // callback1 and callback2 will not be executed!
|
|
114
|
-
```
|
|
115
|
-
@method off
|
|
116
|
-
@for rsvp
|
|
117
|
-
@private
|
|
118
|
-
@param {String} eventName event to stop listening to
|
|
119
|
-
@param {Function} [callback] optional argument. If given, only the function
|
|
120
|
-
given will be removed from the event's callback queue. If no `callback`
|
|
121
|
-
argument is given, all callbacks will be removed from the event's callback
|
|
122
|
-
queue.
|
|
123
|
-
*/
|
|
124
|
-
off: function (eventName, callback) {
|
|
125
|
-
var allCallbacks = callbacksFor(this);
|
|
126
|
-
if (!callback) {
|
|
127
|
-
allCallbacks[eventName] = [];
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
var callbacks = allCallbacks[eventName];
|
|
131
|
-
var index = callbacks.indexOf(callback);
|
|
132
|
-
if (index !== -1) {
|
|
133
|
-
callbacks.splice(index, 1);
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
/**
|
|
137
|
-
Use `trigger` to fire custom events. For example:
|
|
138
|
-
```javascript
|
|
139
|
-
object.on('foo', function(){
|
|
140
|
-
console.log('foo event happened!');
|
|
141
|
-
});
|
|
142
|
-
object.trigger('foo');
|
|
143
|
-
// 'foo event happened!' logged to the console
|
|
144
|
-
```
|
|
145
|
-
You can also pass a value as a second argument to `trigger` that will be
|
|
146
|
-
passed as an argument to all event listeners for the event:
|
|
147
|
-
```javascript
|
|
148
|
-
object.on('foo', function(value){
|
|
149
|
-
console.log(value.name);
|
|
150
|
-
});
|
|
151
|
-
object.trigger('foo', { name: 'bar' });
|
|
152
|
-
// 'bar' logged to the console
|
|
153
|
-
```
|
|
154
|
-
@method trigger
|
|
155
|
-
@for rsvp
|
|
156
|
-
@private
|
|
157
|
-
@param {String} eventName name of the event to be triggered
|
|
158
|
-
@param {*} [options] optional value to be passed to any event handlers for
|
|
159
|
-
the given `eventName`
|
|
160
|
-
*/
|
|
161
|
-
trigger: function (eventName, options, label) {
|
|
162
|
-
var allCallbacks = callbacksFor(this);
|
|
163
|
-
var callbacks = allCallbacks[eventName];
|
|
164
|
-
if (callbacks) {
|
|
165
|
-
// Don't cache the callbacks.length since it may grow
|
|
166
|
-
var callback = void 0;
|
|
167
|
-
for (var i = 0; i < callbacks.length; i++) {
|
|
168
|
-
callback = callbacks[i];
|
|
169
|
-
callback(options, label);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
46
|
+
// sync
|
|
47
|
+
// iterate over records in payload.data
|
|
48
|
+
// for each record
|
|
49
|
+
// assert that record.relationships[inverse] is either undefined (so we can fix it)
|
|
50
|
+
// or provide a data: {id, type} that matches the record that requested it
|
|
51
|
+
// return the relationship data for the parent
|
|
52
|
+
function syncRelationshipDataFromLink(store, payload, parentIdentifier, relationship) {
|
|
53
|
+
// ensure the right hand side (incoming payload) points to the parent record that
|
|
54
|
+
// requested this relationship
|
|
55
|
+
let relationshipData = payload.data ? iterateData(payload.data, (data, index) => {
|
|
56
|
+
const {
|
|
57
|
+
id,
|
|
58
|
+
type
|
|
59
|
+
} = data;
|
|
60
|
+
ensureRelationshipIsSetToParent(data, parentIdentifier, store, relationship, index);
|
|
61
|
+
return {
|
|
62
|
+
id,
|
|
63
|
+
type
|
|
64
|
+
};
|
|
65
|
+
}) : null;
|
|
66
|
+
const relatedDataHash = {};
|
|
67
|
+
if ('meta' in payload) {
|
|
68
|
+
relatedDataHash.meta = payload.meta;
|
|
172
69
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
instrument: false
|
|
176
|
-
};
|
|
177
|
-
EventTarget['mixin'](config);
|
|
178
|
-
function configure(name, value) {
|
|
179
|
-
if (arguments.length === 2) {
|
|
180
|
-
config[name] = value;
|
|
181
|
-
} else {
|
|
182
|
-
return config[name];
|
|
70
|
+
if ('links' in payload) {
|
|
71
|
+
relatedDataHash.links = payload.links;
|
|
183
72
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
function scheduleFlush() {
|
|
187
|
-
setTimeout(function () {
|
|
188
|
-
for (var i = 0; i < queue.length; i++) {
|
|
189
|
-
var entry = queue[i];
|
|
190
|
-
var payload = entry.payload;
|
|
191
|
-
payload.guid = payload.key + payload.id;
|
|
192
|
-
payload.childGuid = payload.key + payload.childId;
|
|
193
|
-
if (payload.error) {
|
|
194
|
-
payload.stack = payload.error.stack;
|
|
195
|
-
}
|
|
196
|
-
config['trigger'](entry.name, entry.payload);
|
|
197
|
-
}
|
|
198
|
-
queue.length = 0;
|
|
199
|
-
}, 50);
|
|
200
|
-
}
|
|
201
|
-
function instrument(eventName, promise, child) {
|
|
202
|
-
if (1 === queue.push({
|
|
203
|
-
name: eventName,
|
|
204
|
-
payload: {
|
|
205
|
-
key: promise._guidKey,
|
|
206
|
-
id: promise._id,
|
|
207
|
-
eventName: eventName,
|
|
208
|
-
detail: promise._result,
|
|
209
|
-
childId: child && child._id,
|
|
210
|
-
label: promise._label,
|
|
211
|
-
timeStamp: Date.now(),
|
|
212
|
-
error: config["instrument-with-stack"] ? new Error(promise._label) : null
|
|
213
|
-
}
|
|
214
|
-
})) {
|
|
215
|
-
scheduleFlush();
|
|
73
|
+
if ('data' in payload) {
|
|
74
|
+
relatedDataHash.data = relationshipData;
|
|
216
75
|
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
`Promise.resolve` returns a promise that will become resolved with the
|
|
221
|
-
passed `value`. It is shorthand for the following:
|
|
222
|
-
|
|
223
|
-
```javascript
|
|
224
|
-
import Promise from 'rsvp';
|
|
225
|
-
|
|
226
|
-
let promise = new Promise(function(resolve, reject){
|
|
227
|
-
resolve(1);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
promise.then(function(value){
|
|
231
|
-
// value === 1
|
|
232
|
-
});
|
|
233
|
-
```
|
|
234
76
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
@method resolve
|
|
248
|
-
@for Promise
|
|
249
|
-
@static
|
|
250
|
-
@param {*} object value that the returned promise will be resolved with
|
|
251
|
-
@param {String} [label] optional string for identifying the returned promise.
|
|
252
|
-
Useful for tooling.
|
|
253
|
-
@return {Promise} a promise that will become fulfilled with the given
|
|
254
|
-
`value`
|
|
255
|
-
*/
|
|
256
|
-
function resolve$$1(object, label) {
|
|
257
|
-
/*jshint validthis:true */
|
|
258
|
-
var Constructor = this;
|
|
259
|
-
if (object && typeof object === 'object' && object.constructor === Constructor) {
|
|
260
|
-
return object;
|
|
261
|
-
}
|
|
262
|
-
var promise = new Constructor(noop, label);
|
|
263
|
-
resolve$1(promise, object);
|
|
264
|
-
return promise;
|
|
265
|
-
}
|
|
266
|
-
function withOwnPromise() {
|
|
267
|
-
return new TypeError('A promises callback cannot return that same promise.');
|
|
268
|
-
}
|
|
269
|
-
function objectOrFunction(x) {
|
|
270
|
-
var type = typeof x;
|
|
271
|
-
return x !== null && (type === 'object' || type === 'function');
|
|
272
|
-
}
|
|
273
|
-
function noop() {}
|
|
274
|
-
var PENDING = void 0;
|
|
275
|
-
var FULFILLED = 1;
|
|
276
|
-
var REJECTED = 2;
|
|
277
|
-
var TRY_CATCH_ERROR = {
|
|
278
|
-
error: null
|
|
279
|
-
};
|
|
280
|
-
function getThen(promise) {
|
|
281
|
-
try {
|
|
282
|
-
return promise.then;
|
|
283
|
-
} catch (error) {
|
|
284
|
-
TRY_CATCH_ERROR.error = error;
|
|
285
|
-
return TRY_CATCH_ERROR;
|
|
77
|
+
// now, push the left hand side (the parent record) to ensure things are in sync, since
|
|
78
|
+
// the payload will be pushed with store._push
|
|
79
|
+
const parentPayload = {
|
|
80
|
+
id: parentIdentifier.id,
|
|
81
|
+
type: parentIdentifier.type,
|
|
82
|
+
relationships: {
|
|
83
|
+
[relationship.key]: relatedDataHash
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
if (!Array.isArray(payload.included)) {
|
|
87
|
+
payload.included = [];
|
|
286
88
|
}
|
|
89
|
+
payload.included.push(parentPayload);
|
|
90
|
+
return payload;
|
|
287
91
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
TRY_CATCH_ERROR.error = e;
|
|
296
|
-
return TRY_CATCH_ERROR;
|
|
92
|
+
function ensureRelationshipIsSetToParent(payload, parentIdentifier, store, parentRelationship, index) {
|
|
93
|
+
let {
|
|
94
|
+
id,
|
|
95
|
+
type
|
|
96
|
+
} = payload;
|
|
97
|
+
if (!payload.relationships) {
|
|
98
|
+
payload.relationships = {};
|
|
297
99
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
100
|
+
let {
|
|
101
|
+
relationships
|
|
102
|
+
} = payload;
|
|
103
|
+
let inverse = getInverse(store, parentIdentifier, parentRelationship, type);
|
|
104
|
+
if (inverse) {
|
|
105
|
+
let {
|
|
106
|
+
inverseKey,
|
|
107
|
+
kind
|
|
108
|
+
} = inverse;
|
|
109
|
+
let relationshipData = relationships[inverseKey] && relationships[inverseKey].data;
|
|
110
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
111
|
+
if (typeof relationshipData !== 'undefined' && !relationshipDataPointsToParent(relationshipData, parentIdentifier)) {
|
|
112
|
+
let inspect = function inspect(thing) {
|
|
113
|
+
return `'${JSON.stringify(thing)}'`;
|
|
114
|
+
};
|
|
115
|
+
let quotedType = inspect(type);
|
|
116
|
+
let quotedInverse = inspect(inverseKey);
|
|
117
|
+
let expected = inspect({
|
|
118
|
+
id: parentIdentifier.id,
|
|
119
|
+
type: parentIdentifier.type
|
|
120
|
+
});
|
|
121
|
+
let expectedModel = `${parentIdentifier.type}:${parentIdentifier.id}`;
|
|
122
|
+
let got = inspect(relationshipData);
|
|
123
|
+
let prefix = typeof index === 'number' ? `data[${index}]` : `data`;
|
|
124
|
+
let path = `${prefix}.relationships.${inverseKey}.data`;
|
|
125
|
+
let other = relationshipData ? `<${relationshipData.type}:${relationshipData.id}>` : null;
|
|
126
|
+
let relationshipFetched = `${expectedModel}.${parentRelationship.kind}("${parentRelationship.name}")`;
|
|
127
|
+
let includedRecord = `<${type}:${id}>`;
|
|
128
|
+
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');
|
|
129
|
+
assert(message);
|
|
319
130
|
}
|
|
320
|
-
sealed = true;
|
|
321
|
-
reject(promise, reason);
|
|
322
|
-
}, 'Settle: ' + (promise._label || ' unknown promise'));
|
|
323
|
-
if (!sealed && result === TRY_CATCH_ERROR) {
|
|
324
|
-
sealed = true;
|
|
325
|
-
var error = TRY_CATCH_ERROR.error;
|
|
326
|
-
TRY_CATCH_ERROR.error = null;
|
|
327
|
-
reject(promise, error);
|
|
328
131
|
}
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
if (thenable._state === FULFILLED) {
|
|
333
|
-
fulfill(promise, thenable._result);
|
|
334
|
-
} else if (thenable._state === REJECTED) {
|
|
335
|
-
thenable._onError = null;
|
|
336
|
-
reject(promise, thenable._result);
|
|
337
|
-
} else {
|
|
338
|
-
subscribe(thenable, undefined, function (value) {
|
|
339
|
-
if (thenable === value) {
|
|
340
|
-
fulfill(promise, value);
|
|
341
|
-
} else {
|
|
342
|
-
resolve$1(promise, value);
|
|
343
|
-
}
|
|
344
|
-
}, function (reason) {
|
|
345
|
-
return reject(promise, reason);
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
function handleMaybeThenable(promise, maybeThenable, then$$1) {
|
|
350
|
-
var isOwnThenable = maybeThenable.constructor === promise.constructor && then$$1 === then && promise.constructor.resolve === resolve$$1;
|
|
351
|
-
if (isOwnThenable) {
|
|
352
|
-
handleOwnThenable(promise, maybeThenable);
|
|
353
|
-
} else if (then$$1 === TRY_CATCH_ERROR) {
|
|
354
|
-
var error = TRY_CATCH_ERROR.error;
|
|
355
|
-
TRY_CATCH_ERROR.error = null;
|
|
356
|
-
reject(promise, error);
|
|
357
|
-
} else if (typeof then$$1 === 'function') {
|
|
358
|
-
handleForeignThenable(promise, maybeThenable, then$$1);
|
|
359
|
-
} else {
|
|
360
|
-
fulfill(promise, maybeThenable);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
function resolve$1(promise, value) {
|
|
364
|
-
if (promise === value) {
|
|
365
|
-
fulfill(promise, value);
|
|
366
|
-
} else if (objectOrFunction(value)) {
|
|
367
|
-
handleMaybeThenable(promise, value, getThen(value));
|
|
368
|
-
} else {
|
|
369
|
-
fulfill(promise, value);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
function publishRejection(promise) {
|
|
373
|
-
if (promise._onError) {
|
|
374
|
-
promise._onError(promise._result);
|
|
375
|
-
}
|
|
376
|
-
publish(promise);
|
|
377
|
-
}
|
|
378
|
-
function fulfill(promise, value) {
|
|
379
|
-
if (promise._state !== PENDING) {
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
promise._result = value;
|
|
383
|
-
promise._state = FULFILLED;
|
|
384
|
-
if (promise._subscribers.length === 0) {
|
|
385
|
-
if (config.instrument) {
|
|
386
|
-
instrument('fulfilled', promise);
|
|
132
|
+
if (kind !== 'hasMany' || typeof relationshipData !== 'undefined') {
|
|
133
|
+
relationships[inverseKey] = relationships[inverseKey] || {};
|
|
134
|
+
relationships[inverseKey].data = fixRelationshipData(relationshipData, kind, parentIdentifier);
|
|
387
135
|
}
|
|
388
|
-
} else {
|
|
389
|
-
config.async(publish, promise);
|
|
390
136
|
}
|
|
391
137
|
}
|
|
392
|
-
function
|
|
393
|
-
|
|
394
|
-
|
|
138
|
+
function inverseForRelationship(store, identifier, key) {
|
|
139
|
+
const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor(identifier)[key];
|
|
140
|
+
if (!definition) {
|
|
141
|
+
return null;
|
|
395
142
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
config.async(publishRejection, promise);
|
|
143
|
+
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);
|
|
144
|
+
return definition.options.inverse;
|
|
399
145
|
}
|
|
400
|
-
function
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
146
|
+
function getInverse(store, parentIdentifier, parentRelationship, type) {
|
|
147
|
+
let {
|
|
148
|
+
name: lhs_relationshipName
|
|
149
|
+
} = parentRelationship;
|
|
150
|
+
let {
|
|
151
|
+
type: parentType
|
|
152
|
+
} = parentIdentifier;
|
|
153
|
+
let inverseKey = inverseForRelationship(store, {
|
|
154
|
+
type: parentType
|
|
155
|
+
}, lhs_relationshipName);
|
|
156
|
+
if (inverseKey) {
|
|
157
|
+
const definition = store.getSchemaDefinitionService().relationshipsDefinitionFor({
|
|
158
|
+
type
|
|
159
|
+
});
|
|
160
|
+
let {
|
|
161
|
+
kind
|
|
162
|
+
} = definition[inverseKey];
|
|
163
|
+
return {
|
|
164
|
+
inverseKey,
|
|
165
|
+
kind
|
|
166
|
+
};
|
|
409
167
|
}
|
|
410
168
|
}
|
|
411
|
-
function
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
if (config.instrument) {
|
|
415
|
-
instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise);
|
|
169
|
+
function relationshipDataPointsToParent(relationshipData, identifier) {
|
|
170
|
+
if (relationshipData === null) {
|
|
171
|
+
return false;
|
|
416
172
|
}
|
|
417
|
-
if (
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
var child = void 0,
|
|
421
|
-
callback = void 0,
|
|
422
|
-
result = promise._result;
|
|
423
|
-
for (var i = 0; i < subscribers.length; i += 3) {
|
|
424
|
-
child = subscribers[i];
|
|
425
|
-
callback = subscribers[i + settled];
|
|
426
|
-
if (child) {
|
|
427
|
-
invokeCallback(settled, child, callback, result);
|
|
428
|
-
} else {
|
|
429
|
-
callback(result);
|
|
173
|
+
if (Array.isArray(relationshipData)) {
|
|
174
|
+
if (relationshipData.length === 0) {
|
|
175
|
+
return false;
|
|
430
176
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
var hasCallback = typeof callback === 'function';
|
|
436
|
-
var value = void 0;
|
|
437
|
-
if (hasCallback) {
|
|
438
|
-
value = tryCatch(callback)(result);
|
|
439
|
-
} else {
|
|
440
|
-
value = result;
|
|
441
|
-
}
|
|
442
|
-
if (promise._state !== PENDING) ;else if (value === promise) {
|
|
443
|
-
reject(promise, withOwnPromise());
|
|
444
|
-
} else if (value === TRY_CATCH_ERROR) {
|
|
445
|
-
var error = TRY_CATCH_ERROR.error;
|
|
446
|
-
TRY_CATCH_ERROR.error = null; // release
|
|
447
|
-
reject(promise, error);
|
|
448
|
-
} else if (hasCallback) {
|
|
449
|
-
resolve$1(promise, value);
|
|
450
|
-
} else if (state === FULFILLED) {
|
|
451
|
-
fulfill(promise, value);
|
|
452
|
-
} else if (state === REJECTED) {
|
|
453
|
-
reject(promise, value);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
function initializePromise(promise, resolver) {
|
|
457
|
-
var resolved = false;
|
|
458
|
-
try {
|
|
459
|
-
resolver(function (value) {
|
|
460
|
-
if (resolved) {
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
resolved = true;
|
|
464
|
-
resolve$1(promise, value);
|
|
465
|
-
}, function (reason) {
|
|
466
|
-
if (resolved) {
|
|
467
|
-
return;
|
|
177
|
+
for (let i = 0; i < relationshipData.length; i++) {
|
|
178
|
+
let entry = relationshipData[i];
|
|
179
|
+
if (validateRelationshipEntry(entry, identifier)) {
|
|
180
|
+
return true;
|
|
468
181
|
}
|
|
469
|
-
|
|
470
|
-
reject(promise, reason);
|
|
471
|
-
});
|
|
472
|
-
} catch (e) {
|
|
473
|
-
reject(promise, e);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
function then(onFulfillment, onRejection, label) {
|
|
477
|
-
var parent = this;
|
|
478
|
-
var state = parent._state;
|
|
479
|
-
if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) {
|
|
480
|
-
config.instrument && instrument('chained', parent, parent);
|
|
481
|
-
return parent;
|
|
482
|
-
}
|
|
483
|
-
parent._onError = null;
|
|
484
|
-
var child = new parent.constructor(noop, label);
|
|
485
|
-
var result = parent._result;
|
|
486
|
-
config.instrument && instrument('chained', parent, child);
|
|
487
|
-
if (state === PENDING) {
|
|
488
|
-
subscribe(parent, child, onFulfillment, onRejection);
|
|
182
|
+
}
|
|
489
183
|
} else {
|
|
490
|
-
|
|
491
|
-
config.async(function () {
|
|
492
|
-
return invokeCallback(state, child, callback, result);
|
|
493
|
-
});
|
|
184
|
+
return validateRelationshipEntry(relationshipData, identifier);
|
|
494
185
|
}
|
|
495
|
-
return
|
|
186
|
+
return false;
|
|
496
187
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
this._init.apply(this, arguments);
|
|
505
|
-
}
|
|
506
|
-
Enumerator.prototype._init = function _init(Constructor, input) {
|
|
507
|
-
var len = input.length || 0;
|
|
508
|
-
this.length = len;
|
|
509
|
-
this._remaining = len;
|
|
510
|
-
this._result = new Array(len);
|
|
511
|
-
this._enumerate(input);
|
|
512
|
-
};
|
|
513
|
-
Enumerator.prototype._enumerate = function _enumerate(input) {
|
|
514
|
-
var length = this.length;
|
|
515
|
-
var promise = this.promise;
|
|
516
|
-
for (var i = 0; promise._state === PENDING && i < length; i++) {
|
|
517
|
-
this._eachEntry(input[i], i, true);
|
|
518
|
-
}
|
|
519
|
-
this._checkFullfillment();
|
|
188
|
+
function fixRelationshipData(relationshipData, relationshipKind, {
|
|
189
|
+
id,
|
|
190
|
+
type
|
|
191
|
+
}) {
|
|
192
|
+
let parentRelationshipData = {
|
|
193
|
+
id,
|
|
194
|
+
type
|
|
520
195
|
};
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
this
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
entry._onError = null;
|
|
534
|
-
this._settledAt(entry._state, i, entry._result, firstPass);
|
|
535
|
-
} else if (typeof then$$1 !== 'function') {
|
|
536
|
-
this._settledAt(FULFILLED, i, entry, firstPass);
|
|
537
|
-
} else if (this._isUsingOwnPromise) {
|
|
538
|
-
var promise = new c(noop);
|
|
539
|
-
handleMaybeThenable(promise, entry, then$$1);
|
|
540
|
-
this._willSettleAt(promise, i, firstPass);
|
|
541
|
-
} else {
|
|
542
|
-
this._willSettleAt(new c(function (resolve) {
|
|
543
|
-
return resolve(entry);
|
|
544
|
-
}), i, firstPass);
|
|
196
|
+
let payload;
|
|
197
|
+
if (relationshipKind === 'hasMany') {
|
|
198
|
+
payload = relationshipData || [];
|
|
199
|
+
if (relationshipData) {
|
|
200
|
+
// these arrays could be massive so this is better than filter
|
|
201
|
+
// Note: this is potentially problematic if type/id are not in the
|
|
202
|
+
// same state of normalization.
|
|
203
|
+
let found = relationshipData.find(v => {
|
|
204
|
+
return v.type === parentRelationshipData.type && v.id === parentRelationshipData.id;
|
|
205
|
+
});
|
|
206
|
+
if (!found) {
|
|
207
|
+
payload.push(parentRelationshipData);
|
|
545
208
|
}
|
|
546
209
|
} else {
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
};
|
|
550
|
-
Enumerator.prototype._eachEntry = function _eachEntry(entry, i, firstPass) {
|
|
551
|
-
if (entry !== null && typeof entry === 'object') {
|
|
552
|
-
this._settleMaybeThenable(entry, i, firstPass);
|
|
553
|
-
} else {
|
|
554
|
-
this._setResultAt(FULFILLED, i, entry, firstPass);
|
|
210
|
+
payload.push(parentRelationshipData);
|
|
555
211
|
}
|
|
556
|
-
};
|
|
557
|
-
Enumerator.prototype._settledAt = function _settledAt(state, i, value, firstPass) {
|
|
558
|
-
var promise = this.promise;
|
|
559
|
-
if (promise._state === PENDING) {
|
|
560
|
-
if (this._abortOnReject && state === REJECTED) {
|
|
561
|
-
reject(promise, value);
|
|
562
|
-
} else {
|
|
563
|
-
this._setResultAt(state, i, value, firstPass);
|
|
564
|
-
this._checkFullfillment();
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
Enumerator.prototype._setResultAt = function _setResultAt(state, i, value, firstPass) {
|
|
569
|
-
this._remaining--;
|
|
570
|
-
this._result[i] = value;
|
|
571
|
-
};
|
|
572
|
-
Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i, firstPass) {
|
|
573
|
-
var _this = this;
|
|
574
|
-
subscribe(promise, undefined, function (value) {
|
|
575
|
-
return _this._settledAt(FULFILLED, i, value, firstPass);
|
|
576
|
-
}, function (reason) {
|
|
577
|
-
return _this._settledAt(REJECTED, i, reason, firstPass);
|
|
578
|
-
});
|
|
579
|
-
};
|
|
580
|
-
return Enumerator;
|
|
581
|
-
}();
|
|
582
|
-
function setSettledResult(state, i, value) {
|
|
583
|
-
this._remaining--;
|
|
584
|
-
if (state === FULFILLED) {
|
|
585
|
-
this._result[i] = {
|
|
586
|
-
state: 'fulfilled',
|
|
587
|
-
value: value
|
|
588
|
-
};
|
|
589
212
|
} else {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
reason: value
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
`Promise.all` accepts an array of promises, and returns a new promise which
|
|
599
|
-
is fulfilled with an array of fulfillment values for the passed promises, or
|
|
600
|
-
rejected with the reason of the first passed promise to be rejected. It casts all
|
|
601
|
-
elements of the passed iterable to promises as it runs this algorithm.
|
|
602
|
-
|
|
603
|
-
Example:
|
|
604
|
-
|
|
605
|
-
```javascript
|
|
606
|
-
import Promise, { resolve } from 'rsvp';
|
|
607
|
-
|
|
608
|
-
let promise1 = resolve(1);
|
|
609
|
-
let promise2 = resolve(2);
|
|
610
|
-
let promise3 = resolve(3);
|
|
611
|
-
let promises = [ promise1, promise2, promise3 ];
|
|
612
|
-
|
|
613
|
-
Promise.all(promises).then(function(array){
|
|
614
|
-
// The array here would be [ 1, 2, 3 ];
|
|
615
|
-
});
|
|
616
|
-
```
|
|
617
|
-
|
|
618
|
-
If any of the `promises` given to `RSVP.all` are rejected, the first promise
|
|
619
|
-
that is rejected will be given as an argument to the returned promises's
|
|
620
|
-
rejection handler. For example:
|
|
621
|
-
|
|
622
|
-
Example:
|
|
623
|
-
|
|
624
|
-
```javascript
|
|
625
|
-
import Promise, { resolve, reject } from 'rsvp';
|
|
626
|
-
|
|
627
|
-
let promise1 = resolve(1);
|
|
628
|
-
let promise2 = reject(new Error("2"));
|
|
629
|
-
let promise3 = reject(new Error("3"));
|
|
630
|
-
let promises = [ promise1, promise2, promise3 ];
|
|
631
|
-
|
|
632
|
-
Promise.all(promises).then(function(array){
|
|
633
|
-
// Code here never runs because there are rejected promises!
|
|
634
|
-
}, function(error) {
|
|
635
|
-
// error.message === "2"
|
|
636
|
-
});
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
@method all
|
|
640
|
-
@for Promise
|
|
641
|
-
@param {Array} entries array of promises
|
|
642
|
-
@param {String} [label] optional string for labeling the promise.
|
|
643
|
-
Useful for tooling.
|
|
644
|
-
@return {Promise} promise that is fulfilled when all `promises` have been
|
|
645
|
-
fulfilled, or rejected if any of them become rejected.
|
|
646
|
-
@static
|
|
647
|
-
*/
|
|
648
|
-
function all(entries, label) {
|
|
649
|
-
if (!Array.isArray(entries)) {
|
|
650
|
-
return this.reject(new TypeError("Promise.all must be called with an array"), label);
|
|
651
|
-
}
|
|
652
|
-
return new Enumerator(this, entries, true /* abort on reject */, label).promise;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
/**
|
|
656
|
-
`Promise.race` returns a new promise which is settled in the same way as the
|
|
657
|
-
first passed promise to settle.
|
|
658
|
-
|
|
659
|
-
Example:
|
|
660
|
-
|
|
661
|
-
```javascript
|
|
662
|
-
import Promise from 'rsvp';
|
|
663
|
-
|
|
664
|
-
let promise1 = new Promise(function(resolve, reject){
|
|
665
|
-
setTimeout(function(){
|
|
666
|
-
resolve('promise 1');
|
|
667
|
-
}, 200);
|
|
668
|
-
});
|
|
669
|
-
|
|
670
|
-
let promise2 = new Promise(function(resolve, reject){
|
|
671
|
-
setTimeout(function(){
|
|
672
|
-
resolve('promise 2');
|
|
673
|
-
}, 100);
|
|
674
|
-
});
|
|
675
|
-
|
|
676
|
-
Promise.race([promise1, promise2]).then(function(result){
|
|
677
|
-
// result === 'promise 2' because it was resolved before promise1
|
|
678
|
-
// was resolved.
|
|
679
|
-
});
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
`Promise.race` is deterministic in that only the state of the first
|
|
683
|
-
settled promise matters. For example, even if other promises given to the
|
|
684
|
-
`promises` array argument are resolved, but the first settled promise has
|
|
685
|
-
become rejected before the other promises became fulfilled, the returned
|
|
686
|
-
promise will become rejected:
|
|
687
|
-
|
|
688
|
-
```javascript
|
|
689
|
-
import Promise from 'rsvp';
|
|
690
|
-
|
|
691
|
-
let promise1 = new Promise(function(resolve, reject){
|
|
692
|
-
setTimeout(function(){
|
|
693
|
-
resolve('promise 1');
|
|
694
|
-
}, 200);
|
|
695
|
-
});
|
|
696
|
-
|
|
697
|
-
let promise2 = new Promise(function(resolve, reject){
|
|
698
|
-
setTimeout(function(){
|
|
699
|
-
reject(new Error('promise 2'));
|
|
700
|
-
}, 100);
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
Promise.race([promise1, promise2]).then(function(result){
|
|
704
|
-
// Code here never runs
|
|
705
|
-
}, function(reason){
|
|
706
|
-
// reason.message === 'promise 2' because promise 2 became rejected before
|
|
707
|
-
// promise 1 became fulfilled
|
|
708
|
-
});
|
|
709
|
-
```
|
|
710
|
-
|
|
711
|
-
An example real-world use case is implementing timeouts:
|
|
712
|
-
|
|
713
|
-
```javascript
|
|
714
|
-
import Promise from 'rsvp';
|
|
715
|
-
|
|
716
|
-
Promise.race([ajax('foo.json'), timeout(5000)])
|
|
717
|
-
```
|
|
718
|
-
|
|
719
|
-
@method race
|
|
720
|
-
@for Promise
|
|
721
|
-
@static
|
|
722
|
-
@param {Array} entries array of promises to observe
|
|
723
|
-
@param {String} [label] optional string for describing the promise returned.
|
|
724
|
-
Useful for tooling.
|
|
725
|
-
@return {Promise} a promise which settles in the same way as the first passed
|
|
726
|
-
promise to settle.
|
|
727
|
-
*/
|
|
728
|
-
function race(entries, label) {
|
|
729
|
-
/*jshint validthis:true */
|
|
730
|
-
var Constructor = this;
|
|
731
|
-
var promise = new Constructor(noop, label);
|
|
732
|
-
if (!Array.isArray(entries)) {
|
|
733
|
-
reject(promise, new TypeError('Promise.race must be called with an array'));
|
|
734
|
-
return promise;
|
|
213
|
+
payload = relationshipData || {};
|
|
214
|
+
Object.assign(payload, parentRelationshipData);
|
|
735
215
|
}
|
|
736
|
-
|
|
737
|
-
subscribe(Constructor.resolve(entries[i]), undefined, function (value) {
|
|
738
|
-
return resolve$1(promise, value);
|
|
739
|
-
}, function (reason) {
|
|
740
|
-
return reject(promise, reason);
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
return promise;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
/**
|
|
747
|
-
`Promise.reject` returns a promise rejected with the passed `reason`.
|
|
748
|
-
It is shorthand for the following:
|
|
749
|
-
|
|
750
|
-
```javascript
|
|
751
|
-
import Promise from 'rsvp';
|
|
752
|
-
|
|
753
|
-
let promise = new Promise(function(resolve, reject){
|
|
754
|
-
reject(new Error('WHOOPS'));
|
|
755
|
-
});
|
|
756
|
-
|
|
757
|
-
promise.then(function(value){
|
|
758
|
-
// Code here doesn't run because the promise is rejected!
|
|
759
|
-
}, function(reason){
|
|
760
|
-
// reason.message === 'WHOOPS'
|
|
761
|
-
});
|
|
762
|
-
```
|
|
763
|
-
|
|
764
|
-
Instead of writing the above, your code now simply becomes the following:
|
|
765
|
-
|
|
766
|
-
```javascript
|
|
767
|
-
import Promise from 'rsvp';
|
|
768
|
-
|
|
769
|
-
let promise = Promise.reject(new Error('WHOOPS'));
|
|
770
|
-
|
|
771
|
-
promise.then(function(value){
|
|
772
|
-
// Code here doesn't run because the promise is rejected!
|
|
773
|
-
}, function(reason){
|
|
774
|
-
// reason.message === 'WHOOPS'
|
|
775
|
-
});
|
|
776
|
-
```
|
|
777
|
-
|
|
778
|
-
@method reject
|
|
779
|
-
@for Promise
|
|
780
|
-
@static
|
|
781
|
-
@param {*} reason value that the returned promise will be rejected with.
|
|
782
|
-
@param {String} [label] optional string for identifying the returned promise.
|
|
783
|
-
Useful for tooling.
|
|
784
|
-
@return {Promise} a promise rejected with the given `reason`.
|
|
785
|
-
*/
|
|
786
|
-
function reject$1(reason, label) {
|
|
787
|
-
/*jshint validthis:true */
|
|
788
|
-
var Constructor = this;
|
|
789
|
-
var promise = new Constructor(noop, label);
|
|
790
|
-
reject(promise, reason);
|
|
791
|
-
return promise;
|
|
216
|
+
return payload;
|
|
792
217
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
218
|
+
function validateRelationshipEntry({
|
|
219
|
+
id
|
|
220
|
+
}, {
|
|
221
|
+
id: parentModelID
|
|
222
|
+
}) {
|
|
223
|
+
return id && id.toString() === parentModelID;
|
|
797
224
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
primary way of interacting with a promise is through its `then` method, which
|
|
805
|
-
registers callbacks to receive either a promise’s eventual value or the reason
|
|
806
|
-
why the promise cannot be fulfilled.
|
|
807
|
-
|
|
808
|
-
Terminology
|
|
809
|
-
-----------
|
|
810
|
-
|
|
811
|
-
- `promise` is an object or function with a `then` method whose behavior conforms to this specification.
|
|
812
|
-
- `thenable` is an object or function that defines a `then` method.
|
|
813
|
-
- `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
|
|
814
|
-
- `exception` is a value that is thrown using the throw statement.
|
|
815
|
-
- `reason` is a value that indicates why a promise was rejected.
|
|
816
|
-
- `settled` the final resting state of a promise, fulfilled or rejected.
|
|
817
|
-
|
|
818
|
-
A promise can be in one of three states: pending, fulfilled, or rejected.
|
|
819
|
-
|
|
820
|
-
Promises that are fulfilled have a fulfillment value and are in the fulfilled
|
|
821
|
-
state. Promises that are rejected have a rejection reason and are in the
|
|
822
|
-
rejected state. A fulfillment value is never a thenable.
|
|
823
|
-
|
|
824
|
-
Promises can also be said to *resolve* a value. If this value is also a
|
|
825
|
-
promise, then the original promise's settled state will match the value's
|
|
826
|
-
settled state. So a promise that *resolves* a promise that rejects will
|
|
827
|
-
itself reject, and a promise that *resolves* a promise that fulfills will
|
|
828
|
-
itself fulfill.
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
Basic Usage:
|
|
832
|
-
------------
|
|
833
|
-
|
|
834
|
-
```js
|
|
835
|
-
let promise = new Promise(function(resolve, reject) {
|
|
836
|
-
// on success
|
|
837
|
-
resolve(value);
|
|
838
|
-
|
|
839
|
-
// on failure
|
|
840
|
-
reject(reason);
|
|
841
|
-
});
|
|
842
|
-
|
|
843
|
-
promise.then(function(value) {
|
|
844
|
-
// on fulfillment
|
|
845
|
-
}, function(reason) {
|
|
846
|
-
// on rejection
|
|
847
|
-
});
|
|
848
|
-
```
|
|
849
|
-
|
|
850
|
-
Advanced Usage:
|
|
851
|
-
---------------
|
|
852
|
-
|
|
853
|
-
Promises shine when abstracting away asynchronous interactions such as
|
|
854
|
-
`XMLHttpRequest`s.
|
|
855
|
-
|
|
856
|
-
```js
|
|
857
|
-
function getJSON(url) {
|
|
858
|
-
return new Promise(function(resolve, reject){
|
|
859
|
-
let xhr = new XMLHttpRequest();
|
|
860
|
-
|
|
861
|
-
xhr.open('GET', url);
|
|
862
|
-
xhr.onreadystatechange = handler;
|
|
863
|
-
xhr.responseType = 'json';
|
|
864
|
-
xhr.setRequestHeader('Accept', 'application/json');
|
|
865
|
-
xhr.send();
|
|
866
|
-
|
|
867
|
-
function handler() {
|
|
868
|
-
if (this.readyState === this.DONE) {
|
|
869
|
-
if (this.status === 200) {
|
|
870
|
-
resolve(this.response);
|
|
871
|
-
} else {
|
|
872
|
-
reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
};
|
|
876
|
-
});
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
getJSON('/posts.json').then(function(json) {
|
|
880
|
-
// on fulfillment
|
|
881
|
-
}, function(reason) {
|
|
882
|
-
// on rejection
|
|
883
|
-
});
|
|
884
|
-
```
|
|
885
|
-
|
|
886
|
-
Unlike callbacks, promises are great composable primitives.
|
|
887
|
-
|
|
888
|
-
```js
|
|
889
|
-
Promise.all([
|
|
890
|
-
getJSON('/posts'),
|
|
891
|
-
getJSON('/comments')
|
|
892
|
-
]).then(function(values){
|
|
893
|
-
values[0] // => postsJSON
|
|
894
|
-
values[1] // => commentsJSON
|
|
895
|
-
|
|
896
|
-
return values;
|
|
897
|
-
});
|
|
898
|
-
```
|
|
899
|
-
|
|
900
|
-
@class Promise
|
|
901
|
-
@public
|
|
902
|
-
@param {function} resolver
|
|
903
|
-
@param {String} [label] optional string for labeling the promise.
|
|
904
|
-
Useful for tooling.
|
|
905
|
-
@constructor
|
|
906
|
-
*/
|
|
907
|
-
|
|
908
|
-
var Promise$1 = function () {
|
|
909
|
-
function Promise(resolver, label) {
|
|
910
|
-
this._id = counter++;
|
|
911
|
-
this._label = label;
|
|
912
|
-
this._state = undefined;
|
|
913
|
-
this._result = undefined;
|
|
914
|
-
this._subscribers = [];
|
|
915
|
-
config.instrument && instrument('created', this);
|
|
916
|
-
if (noop !== resolver) {
|
|
917
|
-
typeof resolver !== 'function' && needsResolver();
|
|
918
|
-
this instanceof Promise ? initializePromise(this, resolver) : needsNew();
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
Promise.prototype._onError = function _onError(reason) {
|
|
922
|
-
var _this = this;
|
|
923
|
-
config.after(function () {
|
|
924
|
-
if (_this._onError) {
|
|
925
|
-
config.trigger('error', reason, _this._label);
|
|
926
|
-
}
|
|
927
|
-
});
|
|
928
|
-
};
|
|
929
|
-
|
|
930
|
-
/**
|
|
931
|
-
`catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
|
|
932
|
-
as the catch block of a try/catch statement.
|
|
933
|
-
|
|
934
|
-
```js
|
|
935
|
-
function findAuthor(){
|
|
936
|
-
throw new Error('couldn\'t find that author');
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
// synchronous
|
|
940
|
-
try {
|
|
941
|
-
findAuthor();
|
|
942
|
-
} catch(reason) {
|
|
943
|
-
// something went wrong
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
// async with promises
|
|
947
|
-
findAuthor().catch(function(reason){
|
|
948
|
-
// something went wrong
|
|
949
|
-
});
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
@method catch
|
|
953
|
-
@param {Function} onRejection
|
|
954
|
-
@param {String} [label] optional string for labeling the promise.
|
|
955
|
-
Useful for tooling.
|
|
956
|
-
@return {Promise}
|
|
957
|
-
*/
|
|
958
|
-
|
|
959
|
-
Promise.prototype.catch = function _catch(onRejection, label) {
|
|
960
|
-
return this.then(undefined, onRejection, label);
|
|
961
|
-
};
|
|
962
|
-
|
|
963
|
-
/**
|
|
964
|
-
`finally` will be invoked regardless of the promise's fate just as native
|
|
965
|
-
try/catch/finally behaves
|
|
966
|
-
|
|
967
|
-
Synchronous example:
|
|
968
|
-
|
|
969
|
-
```js
|
|
970
|
-
findAuthor() {
|
|
971
|
-
if (Math.random() > 0.5) {
|
|
972
|
-
throw new Error();
|
|
973
|
-
}
|
|
974
|
-
return new Author();
|
|
225
|
+
const PotentialLegacyOperations = new Set(['findRecord', 'findAll', 'query', 'queryRecord', 'findBelongsTo', 'findHasMany', 'updateRecord', 'createRecord', 'deleteRecord']);
|
|
226
|
+
const LegacyNetworkHandler = {
|
|
227
|
+
request(context, next) {
|
|
228
|
+
// if we are not a legacy request, move on
|
|
229
|
+
if (context.request.url || !context.request.op || !PotentialLegacyOperations.has(context.request.op)) {
|
|
230
|
+
return next(context.request);
|
|
975
231
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
} finally {
|
|
982
|
-
// always runs
|
|
983
|
-
// doesn't affect the return value
|
|
232
|
+
const {
|
|
233
|
+
store
|
|
234
|
+
} = context.request;
|
|
235
|
+
if (!store._fetchManager) {
|
|
236
|
+
store._fetchManager = new FetchManager(store);
|
|
984
237
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
var constructor = promise.constructor;
|
|
1007
|
-
if (typeof callback === 'function') {
|
|
1008
|
-
return promise.then(function (value) {
|
|
1009
|
-
return constructor.resolve(callback()).then(function () {
|
|
1010
|
-
return value;
|
|
1011
|
-
});
|
|
1012
|
-
}, function (reason) {
|
|
1013
|
-
return constructor.resolve(callback()).then(function () {
|
|
1014
|
-
throw reason;
|
|
1015
|
-
});
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
return promise.then(callback, callback);
|
|
1019
|
-
};
|
|
1020
|
-
return Promise;
|
|
1021
|
-
}();
|
|
1022
|
-
Promise$1.cast = resolve$$1; // deprecated
|
|
1023
|
-
Promise$1.all = all;
|
|
1024
|
-
Promise$1.race = race;
|
|
1025
|
-
Promise$1.resolve = resolve$$1;
|
|
1026
|
-
Promise$1.reject = reject$1;
|
|
1027
|
-
Promise$1.prototype._guidKey = guidKey;
|
|
1028
|
-
|
|
1029
|
-
/**
|
|
1030
|
-
The primary way of interacting with a promise is through its `then` method,
|
|
1031
|
-
which registers callbacks to receive either a promise's eventual value or the
|
|
1032
|
-
reason why the promise cannot be fulfilled.
|
|
1033
|
-
|
|
1034
|
-
```js
|
|
1035
|
-
findUser().then(function(user){
|
|
1036
|
-
// user is available
|
|
1037
|
-
}, function(reason){
|
|
1038
|
-
// user is unavailable, and you are given the reason why
|
|
1039
|
-
});
|
|
1040
|
-
```
|
|
1041
|
-
|
|
1042
|
-
Chaining
|
|
1043
|
-
--------
|
|
1044
|
-
|
|
1045
|
-
The return value of `then` is itself a promise. This second, 'downstream'
|
|
1046
|
-
promise is resolved with the return value of the first promise's fulfillment
|
|
1047
|
-
or rejection handler, or rejected if the handler throws an exception.
|
|
1048
|
-
|
|
1049
|
-
```js
|
|
1050
|
-
findUser().then(function (user) {
|
|
1051
|
-
return user.name;
|
|
1052
|
-
}, function (reason) {
|
|
1053
|
-
return 'default name';
|
|
1054
|
-
}).then(function (userName) {
|
|
1055
|
-
// If `findUser` fulfilled, `userName` will be the user's name, otherwise it
|
|
1056
|
-
// will be `'default name'`
|
|
1057
|
-
});
|
|
1058
|
-
|
|
1059
|
-
findUser().then(function (user) {
|
|
1060
|
-
throw new Error('Found user, but still unhappy');
|
|
1061
|
-
}, function (reason) {
|
|
1062
|
-
throw new Error('`findUser` rejected and we\'re unhappy');
|
|
1063
|
-
}).then(function (value) {
|
|
1064
|
-
// never reached
|
|
1065
|
-
}, function (reason) {
|
|
1066
|
-
// if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
|
|
1067
|
-
// If `findUser` rejected, `reason` will be '`findUser` rejected and we\'re unhappy'.
|
|
1068
|
-
});
|
|
1069
|
-
```
|
|
1070
|
-
If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
|
|
1071
|
-
|
|
1072
|
-
```js
|
|
1073
|
-
findUser().then(function (user) {
|
|
1074
|
-
throw new PedagogicalException('Upstream error');
|
|
1075
|
-
}).then(function (value) {
|
|
1076
|
-
// never reached
|
|
1077
|
-
}).then(function (value) {
|
|
1078
|
-
// never reached
|
|
1079
|
-
}, function (reason) {
|
|
1080
|
-
// The `PedgagocialException` is propagated all the way down to here
|
|
1081
|
-
});
|
|
1082
|
-
```
|
|
1083
|
-
|
|
1084
|
-
Assimilation
|
|
1085
|
-
------------
|
|
1086
|
-
|
|
1087
|
-
Sometimes the value you want to propagate to a downstream promise can only be
|
|
1088
|
-
retrieved asynchronously. This can be achieved by returning a promise in the
|
|
1089
|
-
fulfillment or rejection handler. The downstream promise will then be pending
|
|
1090
|
-
until the returned promise is settled. This is called *assimilation*.
|
|
1091
|
-
|
|
1092
|
-
```js
|
|
1093
|
-
findUser().then(function (user) {
|
|
1094
|
-
return findCommentsByAuthor(user);
|
|
1095
|
-
}).then(function (comments) {
|
|
1096
|
-
// The user's comments are now available
|
|
1097
|
-
});
|
|
1098
|
-
```
|
|
1099
|
-
|
|
1100
|
-
If the assimliated promise rejects, then the downstream promise will also reject.
|
|
1101
|
-
|
|
1102
|
-
```js
|
|
1103
|
-
findUser().then(function (user) {
|
|
1104
|
-
return findCommentsByAuthor(user);
|
|
1105
|
-
}).then(function (comments) {
|
|
1106
|
-
// If `findCommentsByAuthor` fulfills, we'll have the value here
|
|
1107
|
-
}, function (reason) {
|
|
1108
|
-
// If `findCommentsByAuthor` rejects, we'll have the reason here
|
|
1109
|
-
});
|
|
1110
|
-
```
|
|
1111
|
-
|
|
1112
|
-
Simple Example
|
|
1113
|
-
--------------
|
|
1114
|
-
|
|
1115
|
-
Synchronous Example
|
|
1116
|
-
|
|
1117
|
-
```javascript
|
|
1118
|
-
let result;
|
|
1119
|
-
|
|
1120
|
-
try {
|
|
1121
|
-
result = findResult();
|
|
1122
|
-
// success
|
|
1123
|
-
} catch(reason) {
|
|
1124
|
-
// failure
|
|
1125
|
-
}
|
|
1126
|
-
```
|
|
1127
|
-
|
|
1128
|
-
Errback Example
|
|
1129
|
-
|
|
1130
|
-
```js
|
|
1131
|
-
findResult(function(result, err){
|
|
1132
|
-
if (err) {
|
|
1133
|
-
// failure
|
|
1134
|
-
} else {
|
|
1135
|
-
// success
|
|
238
|
+
switch (context.request.op) {
|
|
239
|
+
case 'findRecord':
|
|
240
|
+
return findRecord(context);
|
|
241
|
+
case 'findAll':
|
|
242
|
+
return findAll(context);
|
|
243
|
+
case 'query':
|
|
244
|
+
return query(context);
|
|
245
|
+
case 'queryRecord':
|
|
246
|
+
return queryRecord(context);
|
|
247
|
+
case 'findBelongsTo':
|
|
248
|
+
return findBelongsTo(context);
|
|
249
|
+
case 'findHasMany':
|
|
250
|
+
return findHasMany(context);
|
|
251
|
+
case 'updateRecord':
|
|
252
|
+
return saveRecord(context);
|
|
253
|
+
case 'createRecord':
|
|
254
|
+
return saveRecord(context);
|
|
255
|
+
case 'deleteRecord':
|
|
256
|
+
return saveRecord(context);
|
|
257
|
+
default:
|
|
258
|
+
return next(context.request);
|
|
1136
259
|
}
|
|
1137
|
-
});
|
|
1138
|
-
```
|
|
1139
|
-
|
|
1140
|
-
Promise Example;
|
|
1141
|
-
|
|
1142
|
-
```javascript
|
|
1143
|
-
findResult().then(function(result){
|
|
1144
|
-
// success
|
|
1145
|
-
}, function(reason){
|
|
1146
|
-
// failure
|
|
1147
|
-
});
|
|
1148
|
-
```
|
|
1149
|
-
|
|
1150
|
-
Advanced Example
|
|
1151
|
-
--------------
|
|
1152
|
-
|
|
1153
|
-
Synchronous Example
|
|
1154
|
-
|
|
1155
|
-
```javascript
|
|
1156
|
-
let author, books;
|
|
1157
|
-
|
|
1158
|
-
try {
|
|
1159
|
-
author = findAuthor();
|
|
1160
|
-
books = findBooksByAuthor(author);
|
|
1161
|
-
// success
|
|
1162
|
-
} catch(reason) {
|
|
1163
|
-
// failure
|
|
1164
260
|
}
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
261
|
+
};
|
|
262
|
+
function findBelongsTo(context) {
|
|
263
|
+
const {
|
|
264
|
+
store,
|
|
265
|
+
data,
|
|
266
|
+
records: identifiers
|
|
267
|
+
} = context.request;
|
|
268
|
+
const {
|
|
269
|
+
options,
|
|
270
|
+
record,
|
|
271
|
+
links,
|
|
272
|
+
useLink,
|
|
273
|
+
field
|
|
274
|
+
} = data;
|
|
275
|
+
const identifier = identifiers?.[0];
|
|
1172
276
|
|
|
277
|
+
// short circuit if we are already loading
|
|
278
|
+
let pendingRequest = identifier && store._fetchManager.getPendingFetch(identifier, options);
|
|
279
|
+
if (pendingRequest) {
|
|
280
|
+
return pendingRequest;
|
|
1173
281
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
282
|
+
if (useLink) {
|
|
283
|
+
return _findBelongsTo(store, record, links.related, field, options);
|
|
1177
284
|
}
|
|
285
|
+
assert(`Expected an identifier`, Array.isArray(identifiers) && identifiers.length === 1);
|
|
286
|
+
const manager = store._fetchManager;
|
|
287
|
+
assertIdentifierHasId(identifier);
|
|
288
|
+
return options.reload ? manager.scheduleFetch(identifier, options, context.request) : manager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
|
|
289
|
+
}
|
|
290
|
+
function findHasMany(context) {
|
|
291
|
+
const {
|
|
292
|
+
store,
|
|
293
|
+
data,
|
|
294
|
+
records: identifiers
|
|
295
|
+
} = context.request;
|
|
296
|
+
const {
|
|
297
|
+
options,
|
|
298
|
+
record,
|
|
299
|
+
links,
|
|
300
|
+
useLink,
|
|
301
|
+
field
|
|
302
|
+
} = data;
|
|
1178
303
|
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
304
|
+
// link case
|
|
305
|
+
if (useLink) {
|
|
306
|
+
const adapter = store.adapterFor(record.type);
|
|
307
|
+
/*
|
|
308
|
+
If a relationship was originally populated by the adapter as a link
|
|
309
|
+
(as opposed to a list of IDs), this method is called when the
|
|
310
|
+
relationship is fetched.
|
|
311
|
+
The link (which is usually a URL) is passed through unchanged, so the
|
|
312
|
+
adapter can make whatever request it wants.
|
|
313
|
+
The usual use-case is for the server to register a URL as a link, and
|
|
314
|
+
then use that URL in the future to make a request for the relationship.
|
|
315
|
+
*/
|
|
316
|
+
assert(`You tried to load a hasMany relationship but you have no adapter (for ${record.type})`, adapter);
|
|
317
|
+
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');
|
|
318
|
+
return _findHasMany(adapter, store, record, links.related, field, options);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// identifiers case
|
|
322
|
+
|
|
323
|
+
const fetches = new Array(identifiers.length);
|
|
324
|
+
const manager = store._fetchManager;
|
|
325
|
+
for (let i = 0; i < identifiers.length; i++) {
|
|
326
|
+
let identifier = identifiers[i];
|
|
327
|
+
// TODO we probably can be lenient here and return from cache for the isNew case
|
|
328
|
+
assertIdentifierHasId(identifier);
|
|
329
|
+
fetches[i] = options.reload ? manager.scheduleFetch(identifier, options, context.request) : manager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
|
|
330
|
+
}
|
|
331
|
+
return Promise.all(fetches);
|
|
332
|
+
}
|
|
333
|
+
function saveRecord(context) {
|
|
334
|
+
const {
|
|
335
|
+
store,
|
|
336
|
+
data,
|
|
337
|
+
op: operation
|
|
338
|
+
} = context.request;
|
|
339
|
+
const {
|
|
340
|
+
options,
|
|
341
|
+
record: identifier
|
|
342
|
+
} = data;
|
|
343
|
+
const saveOptions = Object.assign({
|
|
344
|
+
[SaveOp]: operation
|
|
345
|
+
}, options);
|
|
346
|
+
const fetchManagerPromise = store._fetchManager.scheduleSave(identifier, saveOptions);
|
|
347
|
+
return fetchManagerPromise.then(payload => {
|
|
348
|
+
if (macroCondition(getOwnConfig().debug.LOG_PAYLOADS)) {
|
|
1184
349
|
try {
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
} catch(reason) {
|
|
1192
|
-
failure(reason);
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
});
|
|
1196
|
-
} catch(error) {
|
|
1197
|
-
failure(err);
|
|
350
|
+
let data = payload ? JSON.parse(JSON.stringify(payload)) : payload;
|
|
351
|
+
// eslint-disable-next-line no-console
|
|
352
|
+
console.log(`EmberData | Payload - ${operation}`, data);
|
|
353
|
+
} catch (e) {
|
|
354
|
+
// eslint-disable-next-line no-console
|
|
355
|
+
console.log(`EmberData | Payload - ${operation}`, payload);
|
|
1198
356
|
}
|
|
1199
|
-
// success
|
|
1200
|
-
}
|
|
1201
|
-
});
|
|
1202
|
-
```
|
|
1203
|
-
|
|
1204
|
-
Promise Example;
|
|
1205
|
-
|
|
1206
|
-
```javascript
|
|
1207
|
-
findAuthor().
|
|
1208
|
-
then(findBooksByAuthor).
|
|
1209
|
-
then(function(books){
|
|
1210
|
-
// found books
|
|
1211
|
-
}).catch(function(reason){
|
|
1212
|
-
// something went wrong
|
|
1213
|
-
});
|
|
1214
|
-
```
|
|
1215
|
-
|
|
1216
|
-
@method then
|
|
1217
|
-
@param {Function} onFulfillment
|
|
1218
|
-
@param {Function} onRejection
|
|
1219
|
-
@param {String} [label] optional string for labeling the promise.
|
|
1220
|
-
Useful for tooling.
|
|
1221
|
-
@return {Promise}
|
|
1222
|
-
*/
|
|
1223
|
-
Promise$1.prototype.then = then;
|
|
1224
|
-
function _possibleConstructorReturn(self, call) {
|
|
1225
|
-
if (!self) {
|
|
1226
|
-
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
1227
|
-
}
|
|
1228
|
-
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
|
1229
|
-
}
|
|
1230
|
-
function _inherits(subClass, superClass) {
|
|
1231
|
-
if (typeof superClass !== "function" && superClass !== null) {
|
|
1232
|
-
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
|
1233
|
-
}
|
|
1234
|
-
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
1235
|
-
constructor: {
|
|
1236
|
-
value: subClass,
|
|
1237
|
-
enumerable: false,
|
|
1238
|
-
writable: true,
|
|
1239
|
-
configurable: true
|
|
1240
357
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
}(Enumerator);
|
|
1257
|
-
AllSettled.prototype._setResultAt = setSettledResult;
|
|
1258
|
-
function _possibleConstructorReturn$1(self, call) {
|
|
1259
|
-
if (!self) {
|
|
1260
|
-
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
1261
|
-
}
|
|
1262
|
-
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
|
1263
|
-
}
|
|
1264
|
-
function _inherits$1(subClass, superClass) {
|
|
1265
|
-
if (typeof superClass !== "function" && superClass !== null) {
|
|
1266
|
-
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
|
1267
|
-
}
|
|
1268
|
-
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
1269
|
-
constructor: {
|
|
1270
|
-
value: subClass,
|
|
1271
|
-
enumerable: false,
|
|
1272
|
-
writable: true,
|
|
1273
|
-
configurable: true
|
|
1274
|
-
}
|
|
1275
|
-
});
|
|
1276
|
-
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
|
1277
|
-
}
|
|
1278
|
-
var PromiseHash = function (_Enumerator) {
|
|
1279
|
-
_inherits$1(PromiseHash, _Enumerator);
|
|
1280
|
-
function PromiseHash(Constructor, object) {
|
|
1281
|
-
var abortOnReject = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
1282
|
-
var label = arguments[3];
|
|
1283
|
-
return _possibleConstructorReturn$1(this, _Enumerator.call(this, Constructor, object, abortOnReject, label));
|
|
1284
|
-
}
|
|
1285
|
-
PromiseHash.prototype._init = function _init(Constructor, object) {
|
|
1286
|
-
this._result = {};
|
|
1287
|
-
this._enumerate(object);
|
|
1288
|
-
};
|
|
1289
|
-
PromiseHash.prototype._enumerate = function _enumerate(input) {
|
|
1290
|
-
var keys = Object.keys(input);
|
|
1291
|
-
var length = keys.length;
|
|
1292
|
-
var promise = this.promise;
|
|
1293
|
-
this._remaining = length;
|
|
1294
|
-
var key = void 0,
|
|
1295
|
-
val = void 0;
|
|
1296
|
-
for (var i = 0; promise._state === PENDING && i < length; i++) {
|
|
1297
|
-
key = keys[i];
|
|
1298
|
-
val = input[key];
|
|
1299
|
-
this._eachEntry(val, key, true);
|
|
1300
|
-
}
|
|
1301
|
-
this._checkFullfillment();
|
|
1302
|
-
};
|
|
1303
|
-
return PromiseHash;
|
|
1304
|
-
}(Enumerator);
|
|
1305
|
-
function _possibleConstructorReturn$2(self, call) {
|
|
1306
|
-
if (!self) {
|
|
1307
|
-
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
1308
|
-
}
|
|
1309
|
-
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
|
1310
|
-
}
|
|
1311
|
-
function _inherits$2(subClass, superClass) {
|
|
1312
|
-
if (typeof superClass !== "function" && superClass !== null) {
|
|
1313
|
-
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
|
1314
|
-
}
|
|
1315
|
-
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
1316
|
-
constructor: {
|
|
1317
|
-
value: subClass,
|
|
1318
|
-
enumerable: false,
|
|
1319
|
-
writable: true,
|
|
1320
|
-
configurable: true
|
|
1321
|
-
}
|
|
1322
|
-
});
|
|
1323
|
-
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
|
1324
|
-
}
|
|
1325
|
-
var HashSettled = function (_PromiseHash) {
|
|
1326
|
-
_inherits$2(HashSettled, _PromiseHash);
|
|
1327
|
-
function HashSettled(Constructor, object, label) {
|
|
1328
|
-
return _possibleConstructorReturn$2(this, _PromiseHash.call(this, Constructor, object, false, label));
|
|
1329
|
-
}
|
|
1330
|
-
return HashSettled;
|
|
1331
|
-
}(PromiseHash);
|
|
1332
|
-
HashSettled.prototype._setResultAt = setSettledResult;
|
|
1333
|
-
function _possibleConstructorReturn$3(self, call) {
|
|
1334
|
-
if (!self) {
|
|
1335
|
-
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
1336
|
-
}
|
|
1337
|
-
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
|
1338
|
-
}
|
|
1339
|
-
function _inherits$3(subClass, superClass) {
|
|
1340
|
-
if (typeof superClass !== "function" && superClass !== null) {
|
|
1341
|
-
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
|
1342
|
-
}
|
|
1343
|
-
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
1344
|
-
constructor: {
|
|
1345
|
-
value: subClass,
|
|
1346
|
-
enumerable: false,
|
|
1347
|
-
writable: true,
|
|
1348
|
-
configurable: true
|
|
1349
|
-
}
|
|
1350
|
-
});
|
|
1351
|
-
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
|
1352
|
-
}
|
|
1353
|
-
var MapEnumerator = function (_Enumerator) {
|
|
1354
|
-
_inherits$3(MapEnumerator, _Enumerator);
|
|
1355
|
-
function MapEnumerator(Constructor, entries, mapFn, label) {
|
|
1356
|
-
return _possibleConstructorReturn$3(this, _Enumerator.call(this, Constructor, entries, true, label, mapFn));
|
|
1357
|
-
}
|
|
1358
|
-
MapEnumerator.prototype._init = function _init(Constructor, input, bool, label, mapFn) {
|
|
1359
|
-
var len = input.length || 0;
|
|
1360
|
-
this.length = len;
|
|
1361
|
-
this._remaining = len;
|
|
1362
|
-
this._result = new Array(len);
|
|
1363
|
-
this._mapFn = mapFn;
|
|
1364
|
-
this._enumerate(input);
|
|
1365
|
-
};
|
|
1366
|
-
MapEnumerator.prototype._setResultAt = function _setResultAt(state, i, value, firstPass) {
|
|
1367
|
-
if (firstPass) {
|
|
1368
|
-
var val = tryCatch(this._mapFn)(value, i);
|
|
1369
|
-
if (val === TRY_CATCH_ERROR) {
|
|
1370
|
-
this._settledAt(REJECTED, i, val.error, false);
|
|
1371
|
-
} else {
|
|
1372
|
-
this._eachEntry(val, i, false);
|
|
358
|
+
let actualIdentifier = identifier;
|
|
359
|
+
/*
|
|
360
|
+
// TODO @runspired re-evaluate the below claim now that
|
|
361
|
+
// the save request pipeline is more streamlined.
|
|
362
|
+
Note to future spelunkers hoping to optimize.
|
|
363
|
+
We rely on this `run` to create a run loop if needed
|
|
364
|
+
that `store._push` and `store.saveRecord` will both share.
|
|
365
|
+
We use `join` because it is often the case that we
|
|
366
|
+
have an outer run loop available still from the first
|
|
367
|
+
call to `store._push`;
|
|
368
|
+
*/
|
|
369
|
+
store._join(() => {
|
|
370
|
+
let data = payload && payload.data;
|
|
371
|
+
if (!data) {
|
|
372
|
+
assert(`Your ${identifier.type} record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response.`, identifier.id);
|
|
1373
373
|
}
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
}
|
|
1378
|
-
};
|
|
1379
|
-
return MapEnumerator;
|
|
1380
|
-
}(Enumerator);
|
|
1381
|
-
|
|
1382
|
-
/**
|
|
1383
|
-
This is a convenient alias for `Promise.resolve`.
|
|
1384
|
-
|
|
1385
|
-
@method resolve
|
|
1386
|
-
@public
|
|
1387
|
-
@static
|
|
1388
|
-
@for rsvp
|
|
1389
|
-
@param {*} value value that the returned promise will be resolved with
|
|
1390
|
-
@param {String} [label] optional string for identifying the returned promise.
|
|
1391
|
-
Useful for tooling.
|
|
1392
|
-
@return {Promise} a promise that will become fulfilled with the given
|
|
1393
|
-
`value`
|
|
1394
|
-
*/
|
|
1395
|
-
function resolve$2(value, label) {
|
|
1396
|
-
return Promise$1.resolve(value, label);
|
|
1397
|
-
}
|
|
1398
|
-
function _possibleConstructorReturn$4(self, call) {
|
|
1399
|
-
if (!self) {
|
|
1400
|
-
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
1401
|
-
}
|
|
1402
|
-
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
|
1403
|
-
}
|
|
1404
|
-
function _inherits$4(subClass, superClass) {
|
|
1405
|
-
if (typeof superClass !== "function" && superClass !== null) {
|
|
1406
|
-
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
|
1407
|
-
}
|
|
1408
|
-
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
1409
|
-
constructor: {
|
|
1410
|
-
value: subClass,
|
|
1411
|
-
enumerable: false,
|
|
1412
|
-
writable: true,
|
|
1413
|
-
configurable: true
|
|
1414
|
-
}
|
|
1415
|
-
});
|
|
1416
|
-
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
|
1417
|
-
}
|
|
1418
|
-
var EMPTY_OBJECT = {};
|
|
1419
|
-
(function (_MapEnumerator) {
|
|
1420
|
-
_inherits$4(FilterEnumerator, _MapEnumerator);
|
|
1421
|
-
function FilterEnumerator() {
|
|
1422
|
-
return _possibleConstructorReturn$4(this, _MapEnumerator.apply(this, arguments));
|
|
1423
|
-
}
|
|
1424
|
-
FilterEnumerator.prototype._checkFullfillment = function _checkFullfillment() {
|
|
1425
|
-
if (this._remaining === 0 && this._result !== null) {
|
|
1426
|
-
var result = this._result.filter(function (val) {
|
|
1427
|
-
return val !== EMPTY_OBJECT;
|
|
1428
|
-
});
|
|
1429
|
-
fulfill(this.promise, result);
|
|
1430
|
-
this._result = null;
|
|
1431
|
-
}
|
|
1432
|
-
};
|
|
1433
|
-
FilterEnumerator.prototype._setResultAt = function _setResultAt(state, i, value, firstPass) {
|
|
1434
|
-
if (firstPass) {
|
|
1435
|
-
this._result[i] = value;
|
|
1436
|
-
var val = tryCatch(this._mapFn)(value, i);
|
|
1437
|
-
if (val === TRY_CATCH_ERROR) {
|
|
1438
|
-
this._settledAt(REJECTED, i, val.error, false);
|
|
1439
|
-
} else {
|
|
1440
|
-
this._eachEntry(val, i, false);
|
|
374
|
+
const identifierCache = store.identifierCache;
|
|
375
|
+
if (operation !== 'deleteRecord' && data) {
|
|
376
|
+
actualIdentifier = identifierCache.updateRecordIdentifier(identifier, data);
|
|
1441
377
|
}
|
|
1442
|
-
} else {
|
|
1443
|
-
this._remaining--;
|
|
1444
|
-
if (!value) {
|
|
1445
|
-
this._result[i] = EMPTY_OBJECT;
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1448
|
-
};
|
|
1449
|
-
return FilterEnumerator;
|
|
1450
|
-
})(MapEnumerator);
|
|
1451
|
-
var len = 0;
|
|
1452
|
-
var vertxNext = void 0;
|
|
1453
|
-
function asap(callback, arg) {
|
|
1454
|
-
queue$1[len] = callback;
|
|
1455
|
-
queue$1[len + 1] = arg;
|
|
1456
|
-
len += 2;
|
|
1457
|
-
if (len === 2) {
|
|
1458
|
-
// If len is 1, that means that we need to schedule an async flush.
|
|
1459
|
-
// If additional callbacks are queued before the queue is flushed, they
|
|
1460
|
-
// will be processed by this flush that we are scheduling.
|
|
1461
|
-
scheduleFlush$1();
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
var browserWindow = typeof window !== 'undefined' ? window : undefined;
|
|
1465
|
-
var browserGlobal = browserWindow || {};
|
|
1466
|
-
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
|
|
1467
|
-
var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
|
|
1468
|
-
|
|
1469
|
-
// test for web worker but not in IE10
|
|
1470
|
-
var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
|
|
1471
378
|
|
|
1472
|
-
//
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
return
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
}
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
return setTimeout(flush, 1);
|
|
1518
|
-
};
|
|
1519
|
-
}
|
|
1520
|
-
var queue$1 = new Array(1000);
|
|
1521
|
-
function flush() {
|
|
1522
|
-
for (var i = 0; i < len; i += 2) {
|
|
1523
|
-
var callback = queue$1[i];
|
|
1524
|
-
var arg = queue$1[i + 1];
|
|
1525
|
-
callback(arg);
|
|
1526
|
-
queue$1[i] = undefined;
|
|
1527
|
-
queue$1[i + 1] = undefined;
|
|
1528
|
-
}
|
|
1529
|
-
len = 0;
|
|
1530
|
-
}
|
|
1531
|
-
function attemptVertex() {
|
|
1532
|
-
try {
|
|
1533
|
-
var vertx = Function('return this')().require('vertx');
|
|
1534
|
-
vertxNext = vertx.runOnLoop || vertx.runOnContext;
|
|
1535
|
-
return useVertxTimer();
|
|
1536
|
-
} catch (e) {
|
|
1537
|
-
return useSetTimeout();
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
var scheduleFlush$1 = void 0;
|
|
1541
|
-
// Decide what async method to use to triggering processing of queued callbacks:
|
|
1542
|
-
if (isNode) {
|
|
1543
|
-
scheduleFlush$1 = useNextTick();
|
|
1544
|
-
} else if (BrowserMutationObserver) {
|
|
1545
|
-
scheduleFlush$1 = useMutationObserver();
|
|
1546
|
-
} else if (isWorker) {
|
|
1547
|
-
scheduleFlush$1 = useMessageChannel();
|
|
1548
|
-
} else if (browserWindow === undefined && typeof require === 'function') {
|
|
1549
|
-
scheduleFlush$1 = attemptVertex();
|
|
1550
|
-
} else {
|
|
1551
|
-
scheduleFlush$1 = useSetTimeout();
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
// defaults
|
|
1555
|
-
config.async = asap;
|
|
1556
|
-
config.after = function (cb) {
|
|
1557
|
-
return setTimeout(cb, 0);
|
|
1558
|
-
};
|
|
1559
|
-
function on() {
|
|
1560
|
-
config.on.apply(config, arguments);
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
// Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`
|
|
1564
|
-
if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {
|
|
1565
|
-
var callbacks = window['__PROMISE_INSTRUMENTATION__'];
|
|
1566
|
-
configure('instrument', true);
|
|
1567
|
-
for (var eventName in callbacks) {
|
|
1568
|
-
if (callbacks.hasOwnProperty(eventName)) {
|
|
1569
|
-
on(eventName, callbacks[eventName]);
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
function _guard(promise, test) {
|
|
1574
|
-
let guarded = promise.finally(() => {
|
|
1575
|
-
if (!test()) {
|
|
1576
|
-
guarded._subscribers.length = 0;
|
|
379
|
+
//We first make sure the primary data has been updated
|
|
380
|
+
const cache = store.cache;
|
|
381
|
+
cache.didCommit(actualIdentifier, data);
|
|
382
|
+
if (payload && payload.included) {
|
|
383
|
+
store._push({
|
|
384
|
+
data: null,
|
|
385
|
+
included: payload.included
|
|
386
|
+
}, true);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
return store.peekRecord(actualIdentifier);
|
|
390
|
+
}).catch(e => {
|
|
391
|
+
let err = e;
|
|
392
|
+
if (!e) {
|
|
393
|
+
err = new Error(`Unknown Error Occurred During Request`);
|
|
394
|
+
} else if (typeof e === 'string') {
|
|
395
|
+
err = new Error(e);
|
|
396
|
+
}
|
|
397
|
+
adapterDidInvalidate(store, identifier, err);
|
|
398
|
+
throw err;
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
function adapterDidInvalidate(store, identifier, error) {
|
|
402
|
+
if (error && error.isAdapterError === true && error.code === 'InvalidError') {
|
|
403
|
+
let serializer = store.serializerFor(identifier.type);
|
|
404
|
+
|
|
405
|
+
// TODO @deprecate extractErrors being called
|
|
406
|
+
// TODO remove extractErrors from the default serializers.
|
|
407
|
+
if (serializer && typeof serializer.extractErrors === 'function') {
|
|
408
|
+
let errorsHash = serializer.extractErrors(store, store.modelFor(identifier.type), error, identifier.id);
|
|
409
|
+
error.errors = errorsHashToArray(errorsHash);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
const cache = store.cache;
|
|
413
|
+
if (error.errors) {
|
|
414
|
+
assert(`Expected the cache in use by resource ${String(identifier)} to have a getErrors(identifier) method for retreiving errors.`, typeof cache.getErrors === 'function');
|
|
415
|
+
let jsonApiErrors = error.errors;
|
|
416
|
+
if (jsonApiErrors.length === 0) {
|
|
417
|
+
jsonApiErrors = [{
|
|
418
|
+
title: 'Invalid Error',
|
|
419
|
+
detail: '',
|
|
420
|
+
source: {
|
|
421
|
+
pointer: '/data'
|
|
422
|
+
}
|
|
423
|
+
}];
|
|
1577
424
|
}
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
425
|
+
cache.commitWasRejected(identifier, jsonApiErrors);
|
|
426
|
+
} else {
|
|
427
|
+
cache.commitWasRejected(identifier);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function makeArray(value) {
|
|
431
|
+
return Array.isArray(value) ? value : [value];
|
|
432
|
+
}
|
|
433
|
+
const PRIMARY_ATTRIBUTE_KEY = 'base';
|
|
434
|
+
function errorsHashToArray(errors) {
|
|
435
|
+
const out = [];
|
|
436
|
+
if (errors) {
|
|
437
|
+
Object.keys(errors).forEach(key => {
|
|
438
|
+
let messages = makeArray(errors[key]);
|
|
439
|
+
for (let i = 0; i < messages.length; i++) {
|
|
440
|
+
let title = 'Invalid Attribute';
|
|
441
|
+
let pointer = `/data/attributes/${key}`;
|
|
442
|
+
if (key === PRIMARY_ATTRIBUTE_KEY) {
|
|
443
|
+
title = 'Invalid Document';
|
|
444
|
+
pointer = `/data`;
|
|
445
|
+
}
|
|
446
|
+
out.push({
|
|
447
|
+
title: title,
|
|
448
|
+
detail: messages[i],
|
|
449
|
+
source: {
|
|
450
|
+
pointer: pointer
|
|
1595
451
|
}
|
|
1596
452
|
});
|
|
1597
453
|
}
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
return _guard(wrapperPromise, () => {
|
|
1602
|
-
return _objectIsAlive(store);
|
|
1603
|
-
});
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
return out;
|
|
1604
457
|
}
|
|
458
|
+
function findRecord(context) {
|
|
459
|
+
const {
|
|
460
|
+
store,
|
|
461
|
+
data
|
|
462
|
+
} = context.request;
|
|
463
|
+
const {
|
|
464
|
+
record: identifier,
|
|
465
|
+
options
|
|
466
|
+
} = data;
|
|
467
|
+
let promise;
|
|
1605
468
|
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
The format of a document is described here:
|
|
1610
|
-
http://jsonapi.org/format/#document-top-level
|
|
469
|
+
// if not loaded start loading
|
|
470
|
+
if (!store._instanceCache.recordIsLoaded(identifier)) {
|
|
471
|
+
promise = store._fetchManager.fetchDataIfNeededForIdentifier(identifier, options, context.request);
|
|
1611
472
|
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
473
|
+
// Refetch if the reload option is passed
|
|
474
|
+
} else if (options.reload) {
|
|
475
|
+
assertIdentifierHasId(identifier);
|
|
476
|
+
promise = store._fetchManager.scheduleFetch(identifier, options, context.request);
|
|
477
|
+
} else {
|
|
478
|
+
let snapshot = null;
|
|
479
|
+
let adapter = store.adapterFor(identifier.type);
|
|
480
|
+
|
|
481
|
+
// Refetch the record if the adapter thinks the record is stale
|
|
482
|
+
if (typeof options.reload === 'undefined' && adapter.shouldReloadRecord && adapter.shouldReloadRecord(store, snapshot = store._fetchManager.createSnapshot(identifier, options))) {
|
|
483
|
+
assertIdentifierHasId(identifier);
|
|
484
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
485
|
+
promise = store._fetchManager.scheduleFetch(identifier, Object.assign({}, options, {
|
|
486
|
+
reload: true
|
|
487
|
+
}), context.request);
|
|
1622
488
|
} else {
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
if ('data' in doc) {
|
|
1628
|
-
if (!(doc.data === null || Array.isArray(doc.data) || typeof doc.data === 'object')) {
|
|
1629
|
-
errors.push('data must be null, an object, or an array');
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
if ('meta' in doc) {
|
|
1633
|
-
if (typeof doc.meta !== 'object') {
|
|
1634
|
-
errors.push('meta must be an object');
|
|
1635
|
-
}
|
|
489
|
+
options.reload = true;
|
|
490
|
+
promise = store._fetchManager.scheduleFetch(identifier, options, context.request);
|
|
1636
491
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
if (typeof doc.jsonapi !== 'object') {
|
|
1649
|
-
errors.push('jsonapi must be an object');
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
|
-
if ('included' in doc) {
|
|
1653
|
-
if (typeof doc.included !== 'object') {
|
|
1654
|
-
errors.push('included must be an array');
|
|
492
|
+
} else {
|
|
493
|
+
// Trigger the background refetch if backgroundReload option is passed
|
|
494
|
+
if (options.backgroundReload !== false && (options.backgroundReload || !adapter.shouldBackgroundReloadRecord || adapter.shouldBackgroundReloadRecord(store, snapshot = snapshot || store._fetchManager.createSnapshot(identifier, options)))) {
|
|
495
|
+
assertIdentifierHasId(identifier);
|
|
496
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
497
|
+
void store._fetchManager.scheduleFetch(identifier, Object.assign({}, options, {
|
|
498
|
+
backgroundReload: true
|
|
499
|
+
}), context.request);
|
|
500
|
+
} else {
|
|
501
|
+
options.backgroundReload = true;
|
|
502
|
+
void store._fetchManager.scheduleFetch(identifier, options, context.request);
|
|
1655
503
|
}
|
|
1656
504
|
}
|
|
505
|
+
|
|
506
|
+
// Return the cached record
|
|
507
|
+
promise = Promise.resolve(identifier);
|
|
1657
508
|
}
|
|
1658
|
-
assert(`Response must be normalized to a valid JSON API document:\n\t* ${errors.join('\n\t* ')}`, errors.length === 0);
|
|
1659
509
|
}
|
|
510
|
+
return promise.then(identifier => store.peekRecord(identifier));
|
|
1660
511
|
}
|
|
1661
|
-
function normalizeResponseHelper(serializer, store, modelClass, payload, id, requestType) {
|
|
1662
|
-
let normalizedResponse = serializer ? serializer.normalizeResponse(store, modelClass, payload, id, requestType) : payload;
|
|
1663
|
-
validateDocumentStructure(normalizedResponse);
|
|
1664
|
-
return normalizedResponse;
|
|
1665
|
-
}
|
|
1666
|
-
const LegacyNetworkHandler = {
|
|
1667
|
-
request(context, next) {
|
|
1668
|
-
// if we are not a legacy request, move on
|
|
1669
|
-
if (context.request.url || !context.request.op) {
|
|
1670
|
-
return next(context.request);
|
|
1671
|
-
}
|
|
1672
|
-
switch (context.request.op) {
|
|
1673
|
-
case 'findAll':
|
|
1674
|
-
return findAll(context);
|
|
1675
|
-
case 'queryRecord':
|
|
1676
|
-
return queryRecord(context);
|
|
1677
|
-
case 'query':
|
|
1678
|
-
return query(context);
|
|
1679
|
-
default:
|
|
1680
|
-
return next(context.request);
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
};
|
|
1684
512
|
function findAll(context) {
|
|
1685
513
|
const {
|
|
1686
514
|
store,
|
|
@@ -1701,35 +529,40 @@ function findAll(context) {
|
|
|
1701
529
|
let fetch;
|
|
1702
530
|
if (shouldReload) {
|
|
1703
531
|
maybeRecordArray && (maybeRecordArray.isUpdating = true);
|
|
1704
|
-
fetch = _findAll(adapter, store, type, snapshotArray);
|
|
532
|
+
fetch = _findAll(adapter, store, type, snapshotArray, context.request, true);
|
|
1705
533
|
} else {
|
|
1706
|
-
fetch = Promise
|
|
534
|
+
fetch = Promise.resolve(store.peekAll(type));
|
|
1707
535
|
if (options.backgroundReload || options.backgroundReload !== false && (!adapter.shouldBackgroundReloadAll || adapter.shouldBackgroundReloadAll(store, snapshotArray))) {
|
|
1708
536
|
maybeRecordArray && (maybeRecordArray.isUpdating = true);
|
|
1709
|
-
void _findAll(adapter, store, type, snapshotArray);
|
|
537
|
+
void _findAll(adapter, store, type, snapshotArray, context.request, false);
|
|
1710
538
|
}
|
|
1711
539
|
}
|
|
1712
540
|
return fetch;
|
|
1713
541
|
}
|
|
1714
|
-
function
|
|
1715
|
-
if (Array.isArray(adapterPayload)) {
|
|
1716
|
-
return true;
|
|
1717
|
-
} else {
|
|
1718
|
-
return Object.keys(adapterPayload || {}).length;
|
|
1719
|
-
}
|
|
1720
|
-
}
|
|
1721
|
-
function _findAll(adapter, store, type, snapshotArray) {
|
|
542
|
+
function _findAll(adapter, store, type, snapshotArray, request, isAsyncFlush) {
|
|
1722
543
|
const schema = store.modelFor(type);
|
|
1723
|
-
let promise = Promise
|
|
1724
|
-
promise =
|
|
1725
|
-
return promise.then(adapterPayload => {
|
|
544
|
+
let promise = Promise.resolve().then(() => adapter.findAll(store, schema, null, snapshotArray));
|
|
545
|
+
promise = promise.then(adapterPayload => {
|
|
1726
546
|
assert(`You made a 'findAll' request for '${type}' records, but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload));
|
|
1727
547
|
const serializer = store.serializerFor(type);
|
|
1728
548
|
const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'findAll');
|
|
1729
|
-
store._push(payload);
|
|
549
|
+
store._push(payload, isAsyncFlush);
|
|
1730
550
|
snapshotArray._recordArray.isUpdating = false;
|
|
551
|
+
if (macroCondition(getOwnConfig().debug.LOG_PAYLOADS)) {
|
|
552
|
+
// eslint-disable-next-line no-console
|
|
553
|
+
console.log(`request: findAll<${type}> background reload complete`);
|
|
554
|
+
}
|
|
1731
555
|
return snapshotArray._recordArray;
|
|
1732
556
|
});
|
|
557
|
+
if (macroCondition(getOwnConfig().env.TESTING)) {
|
|
558
|
+
if (!request.disableTestWaiter) {
|
|
559
|
+
const {
|
|
560
|
+
waitForPromise
|
|
561
|
+
} = importSync('@ember/test-waiters');
|
|
562
|
+
promise = waitForPromise(promise);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return promise;
|
|
1733
566
|
}
|
|
1734
567
|
function query(context) {
|
|
1735
568
|
const {
|
|
@@ -1750,19 +583,18 @@ function query(context) {
|
|
|
1750
583
|
type,
|
|
1751
584
|
query
|
|
1752
585
|
});
|
|
1753
|
-
if (macroCondition(
|
|
586
|
+
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
1754
587
|
options = Object.assign({}, options);
|
|
1755
588
|
delete options._recordArray;
|
|
1756
589
|
} else {
|
|
1757
590
|
delete options._recordArray;
|
|
1758
591
|
}
|
|
1759
592
|
const schema = store.modelFor(type);
|
|
1760
|
-
let promise = Promise
|
|
1761
|
-
promise = guardDestroyedStore(promise, store, macroCondition(isDevelopingApp()) ? `DS: Handle Adapter#query of ${type}` : ``);
|
|
593
|
+
let promise = Promise.resolve().then(() => adapter.query(store, schema, query, recordArray, options));
|
|
1762
594
|
return promise.then(adapterPayload => {
|
|
1763
595
|
const serializer = store.serializerFor(type);
|
|
1764
596
|
const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'query');
|
|
1765
|
-
const identifiers = store._push(payload);
|
|
597
|
+
const identifiers = store._push(payload, true);
|
|
1766
598
|
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));
|
|
1767
599
|
store.recordArrayManager.populateManagedArray(recordArray, identifiers, payload);
|
|
1768
600
|
return recordArray;
|
|
@@ -1785,13 +617,13 @@ function queryRecord(context) {
|
|
|
1785
617
|
assert(`You tried to make a query but you have no adapter (for ${type})`, adapter);
|
|
1786
618
|
assert(`You tried to make a query but your adapter does not implement 'queryRecord'`, typeof adapter.queryRecord === 'function');
|
|
1787
619
|
const schema = store.modelFor(type);
|
|
1788
|
-
let promise = Promise
|
|
1789
|
-
promise = guardDestroyedStore(promise, store, macroCondition(isDevelopingApp()) ? `DS: Handle Adapter#queryRecord of ${type}` : ``);
|
|
620
|
+
let promise = Promise.resolve().then(() => adapter.queryRecord(store, schema, query, options));
|
|
1790
621
|
return promise.then(adapterPayload => {
|
|
1791
622
|
const serializer = store.serializerFor(type);
|
|
1792
623
|
const payload = normalizeResponseHelper(serializer, store, schema, adapterPayload, null, 'queryRecord');
|
|
1793
624
|
assertSingleResourceDocument(payload);
|
|
1794
|
-
|
|
625
|
+
const identifier = store._push(payload, true);
|
|
626
|
+
return identifier ? store.peekRecord(identifier) : null;
|
|
1795
627
|
});
|
|
1796
628
|
}
|
|
1797
629
|
export { LegacyNetworkHandler };
|