relay-runtime 7.0.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +34 -0
  2. package/handlers/connection/ConnectionHandler.js.flow +549 -0
  3. package/handlers/connection/ConnectionInterface.js.flow +92 -0
  4. package/index.js +1 -1
  5. package/index.js.flow +314 -0
  6. package/lib/handlers/RelayDefaultHandlerProvider.js +3 -2
  7. package/lib/handlers/connection/{RelayConnectionHandler.js → ConnectionHandler.js} +34 -35
  8. package/lib/handlers/connection/{RelayConnectionInterface.js → ConnectionInterface.js} +3 -30
  9. package/lib/index.js +29 -27
  10. package/lib/mutations/RelayDeclarativeMutationConfig.js +30 -52
  11. package/lib/mutations/RelayRecordProxy.js +6 -3
  12. package/lib/mutations/RelayRecordSourceMutator.js +3 -9
  13. package/lib/mutations/RelayRecordSourceProxy.js +21 -24
  14. package/lib/mutations/RelayRecordSourceSelectorProxy.js +18 -14
  15. package/lib/mutations/applyOptimisticMutation.js +2 -1
  16. package/lib/mutations/commitLocalUpdate.js +1 -0
  17. package/lib/mutations/commitMutation.js +26 -8
  18. package/lib/mutations/validateMutation.js +21 -11
  19. package/lib/network/ConvertToExecuteFunction.js +1 -0
  20. package/lib/network/RelayNetwork.js +1 -0
  21. package/lib/network/RelayNetworkTypes.js +1 -0
  22. package/lib/network/RelayObservable.js +10 -9
  23. package/lib/network/RelayQueryResponseCache.js +9 -7
  24. package/lib/query/{RelayModernGraphQLTag.js → GraphQLTag.js} +15 -8
  25. package/lib/query/fetchQuery.js +2 -1
  26. package/lib/query/fetchQueryInternal.js +30 -20
  27. package/lib/store/ClientID.js +1 -0
  28. package/lib/store/DataChecker.js +47 -97
  29. package/lib/store/RelayConcreteVariables.js +7 -2
  30. package/lib/store/RelayModernEnvironment.js +82 -41
  31. package/lib/store/RelayModernFragmentSpecResolver.js +61 -21
  32. package/lib/store/RelayModernOperationDescriptor.js +2 -1
  33. package/lib/store/RelayModernQueryExecutor.js +476 -333
  34. package/lib/store/RelayModernRecord.js +39 -9
  35. package/lib/store/RelayModernSelector.js +2 -1
  36. package/lib/store/RelayModernStore.js +359 -371
  37. package/lib/store/RelayOperationTracker.js +36 -78
  38. package/lib/store/RelayOptimisticRecordSource.js +8 -5
  39. package/lib/store/RelayPublishQueue.js +66 -53
  40. package/lib/store/RelayReader.js +2 -24
  41. package/lib/store/RelayRecordSource.js +3 -9
  42. package/lib/store/RelayRecordSourceMapImpl.js +14 -18
  43. package/lib/store/RelayRecordState.js +1 -0
  44. package/lib/store/RelayReferenceMarker.js +8 -58
  45. package/lib/store/RelayResponseNormalizer.js +15 -144
  46. package/lib/store/RelayStoreTypes.js +1 -0
  47. package/lib/store/RelayStoreUtils.js +34 -10
  48. package/lib/store/StoreInspector.js +11 -5
  49. package/lib/store/ViewerPattern.js +1 -0
  50. package/lib/store/cloneRelayHandleSourceField.js +1 -0
  51. package/lib/store/createFragmentSpecResolver.js +1 -0
  52. package/lib/store/createRelayContext.js +1 -0
  53. package/lib/store/defaultGetDataID.js +1 -0
  54. package/lib/store/hasOverlappingIDs.js +1 -0
  55. package/lib/store/isRelayModernEnvironment.js +1 -0
  56. package/lib/store/normalizeRelayPayload.js +8 -4
  57. package/lib/store/readInlineData.js +2 -1
  58. package/lib/subscription/requestSubscription.js +6 -3
  59. package/lib/util/JSResourceTypes.flow.js +12 -0
  60. package/lib/util/NormalizationNode.js +1 -0
  61. package/lib/util/ReaderNode.js +1 -0
  62. package/lib/util/RelayConcreteNode.js +3 -0
  63. package/lib/util/RelayDefaultHandleKey.js +1 -0
  64. package/lib/util/RelayError.js +2 -1
  65. package/lib/util/RelayFeatureFlags.js +3 -2
  66. package/lib/util/RelayProfiler.js +1 -0
  67. package/lib/util/RelayReplaySubject.js +2 -3
  68. package/lib/util/RelayRuntimeTypes.js +1 -0
  69. package/lib/util/createPayloadFor3DField.js +34 -0
  70. package/lib/util/deepFreeze.js +1 -0
  71. package/lib/util/generateID.js +1 -0
  72. package/lib/util/getFragmentIdentifier.js +1 -0
  73. package/lib/util/getRelayHandleKey.js +1 -0
  74. package/lib/util/getRequestIdentifier.js +1 -0
  75. package/lib/util/isPromise.js +1 -0
  76. package/lib/util/isScalarAndEqual.js +1 -0
  77. package/lib/util/recycleNodesInto.js +1 -0
  78. package/lib/util/resolveImmediate.js +1 -0
  79. package/lib/util/stableCopy.js +1 -0
  80. package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
  81. package/mutations/RelayRecordProxy.js.flow +165 -0
  82. package/mutations/RelayRecordSourceMutator.js.flow +238 -0
  83. package/mutations/RelayRecordSourceProxy.js.flow +164 -0
  84. package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
  85. package/mutations/applyOptimisticMutation.js.flow +76 -0
  86. package/mutations/commitLocalUpdate.js.flow +24 -0
  87. package/mutations/commitMutation.js.flow +184 -0
  88. package/mutations/validateMutation.js.flow +211 -0
  89. package/network/ConvertToExecuteFunction.js.flow +49 -0
  90. package/network/RelayNetwork.js.flow +84 -0
  91. package/network/RelayNetworkTypes.js.flow +123 -0
  92. package/network/RelayObservable.js.flow +634 -0
  93. package/network/RelayQueryResponseCache.js.flow +111 -0
  94. package/package.json +1 -1
  95. package/query/GraphQLTag.js.flow +166 -0
  96. package/query/fetchQuery.js.flow +47 -0
  97. package/query/fetchQueryInternal.js.flow +349 -0
  98. package/relay-runtime.js +2 -2
  99. package/relay-runtime.min.js +2 -2
  100. package/store/ClientID.js.flow +43 -0
  101. package/store/DataChecker.js.flow +426 -0
  102. package/store/RelayConcreteVariables.js.flow +96 -0
  103. package/store/RelayModernEnvironment.js.flow +526 -0
  104. package/store/RelayModernFragmentSpecResolver.js.flow +426 -0
  105. package/store/RelayModernOperationDescriptor.js.flow +88 -0
  106. package/store/RelayModernQueryExecutor.js.flow +1327 -0
  107. package/store/RelayModernRecord.js.flow +403 -0
  108. package/store/RelayModernSelector.js.flow +444 -0
  109. package/store/RelayModernStore.js.flow +757 -0
  110. package/store/RelayOperationTracker.js.flow +164 -0
  111. package/store/RelayOptimisticRecordSource.js.flow +119 -0
  112. package/store/RelayPublishQueue.js.flow +401 -0
  113. package/store/RelayReader.js.flow +376 -0
  114. package/store/RelayRecordSource.js.flow +29 -0
  115. package/store/RelayRecordSourceMapImpl.js.flow +87 -0
  116. package/store/RelayRecordState.js.flow +37 -0
  117. package/store/RelayReferenceMarker.js.flow +236 -0
  118. package/store/RelayResponseNormalizer.js.flow +556 -0
  119. package/store/RelayStoreTypes.js.flow +873 -0
  120. package/store/RelayStoreUtils.js.flow +218 -0
  121. package/store/StoreInspector.js.flow +173 -0
  122. package/store/ViewerPattern.js.flow +26 -0
  123. package/store/cloneRelayHandleSourceField.js.flow +66 -0
  124. package/store/createFragmentSpecResolver.js.flow +55 -0
  125. package/store/createRelayContext.js.flow +44 -0
  126. package/store/defaultGetDataID.js.flow +27 -0
  127. package/store/hasOverlappingIDs.js.flow +34 -0
  128. package/store/isRelayModernEnvironment.js.flow +27 -0
  129. package/store/normalizeRelayPayload.js.flow +51 -0
  130. package/store/readInlineData.js.flow +75 -0
  131. package/subscription/requestSubscription.js.flow +100 -0
  132. package/util/JSResourceTypes.flow.js.flow +20 -0
  133. package/util/NormalizationNode.js.flow +191 -0
  134. package/util/ReaderNode.js.flow +208 -0
  135. package/util/RelayConcreteNode.js.flow +80 -0
  136. package/util/RelayDefaultHandleKey.js.flow +17 -0
  137. package/util/RelayError.js.flow +33 -0
  138. package/util/RelayFeatureFlags.js.flow +30 -0
  139. package/util/RelayProfiler.js.flow +284 -0
  140. package/util/RelayReplaySubject.js.flow +134 -0
  141. package/util/RelayRuntimeTypes.js.flow +70 -0
  142. package/util/createPayloadFor3DField.js.flow +43 -0
  143. package/util/deepFreeze.js.flow +36 -0
  144. package/util/generateID.js.flow +21 -0
  145. package/util/getFragmentIdentifier.js.flow +52 -0
  146. package/util/getRelayHandleKey.js.flow +41 -0
  147. package/util/getRequestIdentifier.js.flow +41 -0
  148. package/util/isPromise.js.flow +21 -0
  149. package/util/isScalarAndEqual.js.flow +26 -0
  150. package/util/recycleNodesInto.js.flow +80 -0
  151. package/util/resolveImmediate.js.flow +30 -0
  152. package/util/stableCopy.js.flow +35 -0
  153. package/lib/handlers/RelayDefaultMissingFieldHandlers.js +0 -26
  154. package/lib/store/RelayConnection.js +0 -36
  155. package/lib/store/RelayConnectionResolver.js +0 -177
  156. package/lib/store/RelayRecordSourceObjectImpl.js +0 -78
  157. package/lib/util/getFragmentSpecIdentifier.js +0 -26
@@ -8,15 +8,24 @@
8
8
  * @format
9
9
  * @emails oncall+relay
10
10
  */
11
+ // flowlint ambiguous-object-type:error
11
12
  'use strict';
12
13
 
13
14
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
14
15
 
15
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
16
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
16
17
 
17
18
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
18
19
 
19
- var RelayConnectionInterface = require('../handlers/connection/RelayConnectionInterface');
20
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
21
+
22
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
23
+
24
+ function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
25
+
26
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
27
+
28
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
20
29
 
21
30
  var RelayError = require('../util/RelayError');
22
31
 
@@ -55,38 +64,45 @@ function execute(config) {
55
64
  */
56
65
 
57
66
 
58
- var Executor =
59
- /*#__PURE__*/
60
- function () {
67
+ var Executor = /*#__PURE__*/function () {
61
68
  function Executor(_ref) {
62
69
  var _this = this;
63
70
 
64
71
  var operation = _ref.operation,
72
+ operationExecutions = _ref.operationExecutions,
65
73
  operationLoader = _ref.operationLoader,
66
74
  optimisticConfig = _ref.optimisticConfig,
67
75
  publishQueue = _ref.publishQueue,
68
76
  scheduler = _ref.scheduler,
69
77
  sink = _ref.sink,
70
78
  source = _ref.source,
79
+ store = _ref.store,
71
80
  updater = _ref.updater,
72
81
  operationTracker = _ref.operationTracker,
73
- getDataID = _ref.getDataID;
82
+ treatMissingFieldsAsNull = _ref.treatMissingFieldsAsNull,
83
+ getDataID = _ref.getDataID,
84
+ isClientPayload = _ref.isClientPayload;
85
+ this._getDataID = getDataID;
86
+ this._treatMissingFieldsAsNull = treatMissingFieldsAsNull;
87
+ this._incrementalPayloadsPending = false;
74
88
  this._incrementalResults = new Map();
75
89
  this._nextSubscriptionId = 0;
76
90
  this._operation = operation;
91
+ this._operationExecutions = operationExecutions;
77
92
  this._operationLoader = operationLoader;
93
+ this._operationTracker = operationTracker;
94
+ this._operationUpdateEpochs = new Map();
78
95
  this._optimisticUpdates = null;
96
+ this._pendingModulePayloadsCount = 0;
79
97
  this._publishQueue = publishQueue;
80
98
  this._scheduler = scheduler;
81
99
  this._sink = sink;
82
100
  this._source = new Map();
83
101
  this._state = 'started';
84
- this._updater = updater;
102
+ this._store = store;
85
103
  this._subscriptions = new Map();
86
- this._operationTracker = operationTracker;
87
- this._getDataID = getDataID;
88
- this._incrementalPayloadsPending = false;
89
- this._pendingModulePayloadsCount = 0;
104
+ this._updater = updater;
105
+ this._isClientPayload = isClientPayload === true;
90
106
  var id = this._nextSubscriptionId++;
91
107
  source.subscribe({
92
108
  complete: function complete() {
@@ -110,7 +126,7 @@ function () {
110
126
  if (optimisticConfig != null) {
111
127
  this._processOptimisticResponse(optimisticConfig.response != null ? {
112
128
  data: optimisticConfig.response
113
- } : null, optimisticConfig.updater);
129
+ } : null, optimisticConfig.updater, false);
114
130
  }
115
131
  } // Cancel any pending execution tasks and mark the executor as completed.
116
132
 
@@ -126,6 +142,8 @@ function () {
126
142
 
127
143
  this._state = 'completed';
128
144
 
145
+ this._operationExecutions["delete"](this._operation.request.identifier);
146
+
129
147
  if (this._subscriptions.size !== 0) {
130
148
  this._subscriptions.forEach(function (sub) {
131
149
  return sub.unsubscribe();
@@ -150,6 +168,42 @@ function () {
150
168
  this._completeOperationTracker();
151
169
  };
152
170
 
171
+ _proto._updateActiveState = function _updateActiveState() {
172
+ var activeState;
173
+
174
+ switch (this._state) {
175
+ case 'started':
176
+ {
177
+ activeState = 'active';
178
+ break;
179
+ }
180
+
181
+ case 'loading_incremental':
182
+ {
183
+ activeState = 'active';
184
+ break;
185
+ }
186
+
187
+ case 'completed':
188
+ {
189
+ activeState = 'inactive';
190
+ break;
191
+ }
192
+
193
+ case 'loading_final':
194
+ {
195
+ activeState = this._pendingModulePayloadsCount > 0 ? 'active' : 'inactive';
196
+ break;
197
+ }
198
+
199
+ default:
200
+ this._state;
201
+ !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernQueryExecutor: invalid executor state.') : invariant(false) : void 0;
202
+ }
203
+
204
+ this._operationExecutions.set(this._operation.request.identifier, activeState);
205
+ };
206
+
153
207
  _proto._schedule = function _schedule(task) {
154
208
  var _this3 = this;
155
209
 
@@ -204,6 +258,8 @@ function () {
204
258
 
205
259
  _proto._start = function _start(id, subscription) {
206
260
  this._subscriptions.set(id, subscription);
261
+
262
+ this._updateActiveState();
207
263
  } // Handle a raw GraphQL response.
208
264
  ;
209
265
 
@@ -217,69 +273,155 @@ function () {
217
273
  });
218
274
  };
219
275
 
220
- _proto._handleNext = function _handleNext(response) {
221
- var _response$extensions, _response$extensions2;
276
+ _proto._handleErrorResponse = function _handleErrorResponse(responses) {
277
+ var _this5 = this;
222
278
 
223
- if (this._state === 'completed') {
224
- return;
225
- }
279
+ var results = [];
280
+ responses.forEach(function (response) {
281
+ if (response.data === null && response.extensions != null && !response.hasOwnProperty('errors')) {
282
+ // Skip extensions-only payloads
283
+ return;
284
+ } else if (response.data == null) {
285
+ // Error if any other payload in the batch is missing data, regardless of whether
286
+ // it had `errors` or not.
287
+ var errors = response.hasOwnProperty('errors') && response.errors != null ? response.errors : null;
288
+ var messages = errors ? errors.map(function (_ref2) {
289
+ var message = _ref2.message;
290
+ return message;
291
+ }).join('\n') : '(No errors)';
292
+ var error = RelayError.create('RelayNetwork', 'No data returned for operation `' + _this5._operation.request.node.params.name + '`, got error(s):\n' + messages + '\n\nSee the error `source` property for more information.');
293
+ error.source = {
294
+ errors: errors,
295
+ operation: _this5._operation.request.node,
296
+ variables: _this5._operation.request.variables
297
+ };
298
+ throw error;
299
+ } else {
300
+ var responseWithData = response;
301
+ results.push(responseWithData);
302
+ }
303
+ });
304
+ return results;
305
+ }
306
+ /**
307
+ * This method return boolean to indicate if the optimistic
308
+ * response has been handled
309
+ */
310
+ ;
226
311
 
227
- if (response.data == null) {
228
- var errors = response.errors;
229
- var messages = errors ? errors.map(function (_ref2) {
230
- var message = _ref2.message;
231
- return message;
232
- }).join('\n') : '(No errors)';
233
- var error = RelayError.create('RelayNetwork', 'No data returned for operation `' + this._operation.request.node.params.name + '`, got error(s):\n' + messages + '\n\nSee the error `source` property for more information.');
234
- error.source = {
235
- errors: errors,
236
- operation: this._operation.request.node,
237
- variables: this._operation.request.variables
238
- };
239
- throw error;
240
- } // Above check ensures that response.data != null
312
+ _proto._handleOptimisticResponses = function _handleOptimisticResponses(responses) {
313
+ var _response$extensions;
241
314
 
315
+ if (responses.length > 1) {
316
+ if (responses.some(function (responsePart) {
317
+ var _responsePart$extensi;
242
318
 
243
- var responseWithData = response;
319
+ return ((_responsePart$extensi = responsePart.extensions) === null || _responsePart$extensi === void 0 ? void 0 : _responsePart$extensi.isOptimistic) === true;
320
+ })) {
321
+ !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Optimistic responses cannot be batched.') : invariant(false) : void 0;
322
+ }
323
+
324
+ return false;
325
+ }
326
+
327
+ var response = responses[0];
244
328
  var isOptimistic = ((_response$extensions = response.extensions) === null || _response$extensions === void 0 ? void 0 : _response$extensions.isOptimistic) === true;
245
329
 
246
330
  if (isOptimistic && this._state !== 'started') {
247
331
  !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernQueryExecutor: optimistic payload received after server payload.') : invariant(false) : void 0;
248
332
  }
249
333
 
250
- var isFinal = ((_response$extensions2 = response.extensions) === null || _response$extensions2 === void 0 ? void 0 : _response$extensions2.is_final) === true;
251
- this._state = isFinal ? 'loading_final' : 'loading_incremental';
334
+ if (isOptimistic) {
335
+ this._processOptimisticResponse(response, null, this._treatMissingFieldsAsNull);
336
+
337
+ this._sink.next(response);
252
338
 
253
- if (isFinal) {
254
- this._incrementalPayloadsPending = false;
339
+ return true;
255
340
  }
256
341
 
257
- if (isOptimistic) {
258
- this._processOptimisticResponse(responseWithData, null);
259
- } else {
260
- var path = response.path,
261
- label = response.label;
262
-
263
- if (path != null || label != null) {
264
- if (typeof label === 'string' && Array.isArray(path)) {
265
- this._processIncrementalResponse({
266
- path: path,
267
- label: label,
268
- response: responseWithData
269
- });
270
- } else {
271
- !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernQueryExecutor: invalid incremental payload, expected ' + '`path` and `label` to either both be null/undefined, or ' + '`path` to be an `Array<string | number>` and `label` to be a ' + '`string`.') : invariant(false) : void 0;
272
- }
273
- } else {
274
- this._processResponse(responseWithData);
342
+ return false;
343
+ };
344
+
345
+ _proto._handleNext = function _handleNext(response) {
346
+ if (this._state === 'completed') {
347
+ return;
348
+ }
349
+
350
+ var responses = Array.isArray(response) ? response : [response];
351
+
352
+ var responsesWithData = this._handleErrorResponse(responses);
353
+
354
+ if (responsesWithData.length === 0) {
355
+ // no results with data, nothing to process
356
+ // this can occur with extensions-only payloads
357
+ var isFinal = responses.some(function (x) {
358
+ var _x$extensions;
359
+
360
+ return ((_x$extensions = x.extensions) === null || _x$extensions === void 0 ? void 0 : _x$extensions.is_final) === true;
361
+ });
362
+
363
+ if (isFinal) {
364
+ this._state = 'loading_final';
365
+
366
+ this._updateActiveState();
367
+
368
+ this._incrementalPayloadsPending = false;
275
369
  }
370
+
371
+ this._sink.next(response);
372
+
373
+ return;
374
+ } // Next, handle optimistic responses
375
+
376
+
377
+ var isOptimistic = this._handleOptimisticResponses(responsesWithData);
378
+
379
+ if (isOptimistic) {
380
+ return;
381
+ }
382
+
383
+ var _partitionGraphQLResp = partitionGraphQLResponses(responsesWithData),
384
+ nonIncrementalResponses = _partitionGraphQLResp[0],
385
+ incrementalResponses = _partitionGraphQLResp[1]; // In theory this doesn't preserve the ordering of the batch.
386
+ // The idea is that a batch is always:
387
+ // * at-most one non-incremental payload
388
+ // * followed zero or more incremental payloads
389
+ // The non-incremental payload can appear if the server sends a batch
390
+ // w the initial payload followed by some early-to-resolve incremental
391
+ // payloads (although, can that even happen?)
392
+
393
+
394
+ if (nonIncrementalResponses.length > 0) {
395
+ var payloadFollowups = this._processResponses(nonIncrementalResponses); // Please note, that we're passing `this._operation` to the publish
396
+ // queue here, which will later passed to the store (via notify)
397
+ // to indicate that this is an operation that cause the store to update
398
+
399
+
400
+ var updatedOwners = this._publishQueue.run(this._operation);
401
+
402
+ this._updateOperationTracker(updatedOwners);
403
+
404
+ this._processPayloadFollowups(payloadFollowups);
405
+ }
406
+
407
+ if (incrementalResponses.length > 0) {
408
+ var _payloadFollowups = this._processIncrementalResponses(incrementalResponses); // For the incremental case, we're only handling follow-up responses
409
+ // for already initiated operation (and we're not passing it to
410
+ // the run(...) call)
411
+
412
+
413
+ var _updatedOwners = this._publishQueue.run();
414
+
415
+ this._updateOperationTracker(_updatedOwners);
416
+
417
+ this._processPayloadFollowups(_payloadFollowups);
276
418
  }
277
419
 
278
420
  this._sink.next(response);
279
421
  };
280
422
 
281
- _proto._processOptimisticResponse = function _processOptimisticResponse(response, updater) {
282
- var _this5 = this;
423
+ _proto._processOptimisticResponse = function _processOptimisticResponse(response, updater, treatMissingFieldsAsNull) {
424
+ var _this6 = this;
283
425
 
284
426
  !(this._optimisticUpdates === null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'environment.execute: only support one optimistic response per ' + 'execute.') : invariant(false) : void 0;
285
427
 
@@ -293,7 +435,8 @@ function () {
293
435
  var payload = normalizeResponse(response, this._operation.root, ROOT_TYPE, {
294
436
  getDataID: this._getDataID,
295
437
  path: [],
296
- request: this._operation.request
438
+ request: this._operation.request,
439
+ treatMissingFieldsAsNull: treatMissingFieldsAsNull
297
440
  });
298
441
  validateOptimisticResponsePayload(payload);
299
442
  optimisticUpdates.push({
@@ -302,49 +445,17 @@ function () {
302
445
  updater: updater
303
446
  });
304
447
 
305
- if (payload.moduleImportPayloads && payload.moduleImportPayloads.length) {
306
- var moduleImportPayloads = payload.moduleImportPayloads;
307
- var operationLoader = this._operationLoader;
308
- !operationLoader ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected an operationLoader to be ' + 'configured when using `@match`.') : invariant(false) : void 0;
309
-
310
- while (moduleImportPayloads.length) {
311
- var moduleImportPayload = moduleImportPayloads.shift();
312
- var operation = operationLoader.get(moduleImportPayload.operationReference);
313
-
314
- if (operation == null) {
315
- continue;
316
- }
317
-
318
- var selector = createNormalizationSelector(operation, moduleImportPayload.dataID, moduleImportPayload.variables);
319
- var modulePayload = normalizeResponse({
320
- data: moduleImportPayload.data
321
- }, selector, moduleImportPayload.typeName, {
322
- getDataID: this._getDataID,
323
- path: moduleImportPayload.path,
324
- request: this._operation.request
325
- });
326
- validateOptimisticResponsePayload(modulePayload);
327
- optimisticUpdates.push({
328
- operation: this._operation,
329
- payload: modulePayload,
330
- updater: null
331
- });
332
-
333
- if (modulePayload.moduleImportPayloads) {
334
- moduleImportPayloads.push.apply(moduleImportPayloads, (0, _toConsumableArray2["default"])(modulePayload.moduleImportPayloads));
335
- }
336
- }
337
- }
448
+ this._processOptimisticFollowups(payload, optimisticUpdates);
338
449
  } else if (updater) {
339
450
  optimisticUpdates.push({
340
451
  operation: this._operation,
341
452
  payload: {
342
- connectionEvents: null,
343
453
  errors: null,
344
454
  fieldPayloads: null,
345
455
  incrementalPlaceholders: null,
346
456
  moduleImportPayloads: null,
347
- source: RelayRecordSource.create()
457
+ source: RelayRecordSource.create(),
458
+ isFinal: false
348
459
  },
349
460
  updater: updater
350
461
  });
@@ -352,41 +463,126 @@ function () {
352
463
 
353
464
  this._optimisticUpdates = optimisticUpdates;
354
465
  optimisticUpdates.forEach(function (update) {
355
- return _this5._publishQueue.applyUpdate(update);
466
+ return _this6._publishQueue.applyUpdate(update);
356
467
  });
357
468
 
358
469
  this._publishQueue.run();
359
470
  };
360
471
 
361
- _proto._processResponse = function _processResponse(response) {
362
- var _this6 = this;
472
+ _proto._processOptimisticFollowups = function _processOptimisticFollowups(payload, optimisticUpdates) {
473
+ if (payload.moduleImportPayloads && payload.moduleImportPayloads.length) {
474
+ var moduleImportPayloads = payload.moduleImportPayloads;
475
+ var operationLoader = this._operationLoader;
476
+ !operationLoader ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected an operationLoader to be ' + 'configured when using `@match`.') : invariant(false) : void 0;
477
+
478
+ var _iterator = _createForOfIteratorHelper(moduleImportPayloads),
479
+ _step;
480
+
481
+ try {
482
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
483
+ var moduleImportPayload = _step.value;
484
+ var operation = operationLoader.get(moduleImportPayload.operationReference);
485
+
486
+ if (operation == null) {
487
+ this._processAsyncOptimisticModuleImport(operationLoader, moduleImportPayload);
488
+ } else {
489
+ var moduleImportOptimisitcUpdates = this._processOptimisticModuleImport(operation, moduleImportPayload);
490
+
491
+ optimisticUpdates.push.apply(optimisticUpdates, (0, _toConsumableArray2["default"])(moduleImportOptimisitcUpdates));
492
+ }
493
+ }
494
+ } catch (err) {
495
+ _iterator.e(err);
496
+ } finally {
497
+ _iterator.f();
498
+ }
499
+ }
500
+ };
501
+
502
+ _proto._normalizeModuleImport = function _normalizeModuleImport(moduleImportPayload, operation) {
503
+ var selector = createNormalizationSelector(operation, moduleImportPayload.dataID, moduleImportPayload.variables);
504
+ return normalizeResponse({
505
+ data: moduleImportPayload.data
506
+ }, selector, moduleImportPayload.typeName, {
507
+ getDataID: this._getDataID,
508
+ path: moduleImportPayload.path,
509
+ request: this._operation.request,
510
+ treatMissingFieldsAsNull: this._treatMissingFieldsAsNull
511
+ });
512
+ };
513
+
514
+ _proto._processOptimisticModuleImport = function _processOptimisticModuleImport(operation, moduleImportPayload) {
515
+ var optimisticUpdates = [];
516
+
517
+ var modulePayload = this._normalizeModuleImport(moduleImportPayload, operation);
518
+
519
+ validateOptimisticResponsePayload(modulePayload);
520
+ optimisticUpdates.push({
521
+ operation: this._operation,
522
+ payload: modulePayload,
523
+ updater: null
524
+ });
525
+
526
+ this._processOptimisticFollowups(modulePayload, optimisticUpdates);
527
+
528
+ return optimisticUpdates;
529
+ };
530
+
531
+ _proto._processAsyncOptimisticModuleImport = function _processAsyncOptimisticModuleImport(operationLoader, moduleImportPayload) {
532
+ var _this7 = this;
533
+
534
+ operationLoader.load(moduleImportPayload.operationReference).then(function (operation) {
535
+ if (operation == null || _this7._state !== 'started') {
536
+ return;
537
+ }
538
+
539
+ var moduleImportOptimisitcUpdates = _this7._processOptimisticModuleImport(operation, moduleImportPayload);
540
+
541
+ moduleImportOptimisitcUpdates.forEach(function (update) {
542
+ return _this7._publishQueue.applyUpdate(update);
543
+ });
544
+
545
+ if (_this7._optimisticUpdates == null) {
546
+ process.env.NODE_ENV !== "production" ? warning(false, 'RelayModernQueryExecutor: Unexpected ModuleImport optimisitc ' + 'update in operation %s.' + _this7._operation.request.node.params.name) : void 0;
547
+ } else {
548
+ var _this$_optimisticUpda;
549
+
550
+ (_this$_optimisticUpda = _this7._optimisticUpdates).push.apply(_this$_optimisticUpda, (0, _toConsumableArray2["default"])(moduleImportOptimisitcUpdates));
551
+
552
+ _this7._publishQueue.run();
553
+ }
554
+ });
555
+ };
556
+
557
+ _proto._processResponses = function _processResponses(responses) {
558
+ var _this8 = this;
363
559
 
364
560
  if (this._optimisticUpdates !== null) {
365
561
  this._optimisticUpdates.forEach(function (update) {
366
- return _this6._publishQueue.revertUpdate(update);
562
+ return _this8._publishQueue.revertUpdate(update);
367
563
  });
368
564
 
369
565
  this._optimisticUpdates = null;
370
566
  }
371
567
 
372
- var payload = normalizeResponse(response, this._operation.root, ROOT_TYPE, {
373
- getDataID: this._getDataID,
374
- path: [],
375
- request: this._operation.request
376
- });
377
568
  this._incrementalPayloadsPending = false;
378
569
 
379
570
  this._incrementalResults.clear();
380
571
 
381
572
  this._source.clear();
382
573
 
383
- this._publishQueue.commitPayload(this._operation, payload, this._updater);
384
-
385
- var updatedOwners = this._publishQueue.run();
574
+ return responses.map(function (payloadPart) {
575
+ var relayPayload = normalizeResponse(payloadPart, _this8._operation.root, ROOT_TYPE, {
576
+ getDataID: _this8._getDataID,
577
+ treatMissingFieldsAsNull: _this8._treatMissingFieldsAsNull,
578
+ path: [],
579
+ request: _this8._operation.request
580
+ });
386
581
 
387
- this._updateOperationTracker(updatedOwners);
582
+ _this8._publishQueue.commitPayload(_this8._operation, relayPayload, _this8._updater);
388
583
 
389
- this._processPayloadFollowups(payload);
584
+ return relayPayload;
585
+ });
390
586
  }
391
587
  /**
392
588
  * Handles any follow-up actions for a Relay payload for @match, @defer,
@@ -394,47 +590,67 @@ function () {
394
590
  */
395
591
  ;
396
592
 
397
- _proto._processPayloadFollowups = function _processPayloadFollowups(payload) {
398
- var _this7 = this;
593
+ _proto._processPayloadFollowups = function _processPayloadFollowups(payloads) {
594
+ var _this9 = this;
399
595
 
400
596
  if (this._state === 'completed') {
401
597
  return;
402
598
  }
403
599
 
404
- var incrementalPlaceholders = payload.incrementalPlaceholders,
405
- moduleImportPayloads = payload.moduleImportPayloads;
600
+ payloads.forEach(function (payload) {
601
+ var incrementalPlaceholders = payload.incrementalPlaceholders,
602
+ moduleImportPayloads = payload.moduleImportPayloads,
603
+ isFinal = payload.isFinal;
604
+ _this9._state = isFinal ? 'loading_final' : 'loading_incremental';
406
605
 
407
- if (moduleImportPayloads && moduleImportPayloads.length !== 0) {
408
- var operationLoader = this._operationLoader;
409
- !operationLoader ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected an operationLoader to be ' + 'configured when using `@match`.') : invariant(false) : void 0;
410
- moduleImportPayloads.forEach(function (moduleImportPayload) {
411
- _this7._processModuleImportPayload(moduleImportPayload, operationLoader);
412
- });
413
- }
606
+ _this9._updateActiveState();
414
607
 
415
- if (incrementalPlaceholders && incrementalPlaceholders.length !== 0) {
416
- this._incrementalPayloadsPending = this._state !== 'loading_final';
417
- incrementalPlaceholders.forEach(function (incrementalPlaceholder) {
418
- _this7._processIncrementalPlaceholder(payload, incrementalPlaceholder);
419
- });
608
+ if (isFinal) {
609
+ _this9._incrementalPayloadsPending = false;
610
+ }
420
611
 
421
- if (this._state === 'loading_final') {
422
- // The query has defer/stream selections that are enabled, but the
423
- // server indicated that this is a "final" payload: no incremental
424
- // payloads will be delivered. Warn that the query was (likely) executed
425
- // on the server in non-streaming mode, with incremental delivery
426
- // disabled.
427
- process.env.NODE_ENV !== "production" ? warning(false, 'RelayModernEnvironment: Operation `%s` contains @defer/@stream ' + 'directives but was executed in non-streaming mode. See ' + 'https://fburl.com/relay-incremental-delivery-non-streaming-warning.', this._operation.request.node.params.name) : void 0; // But eagerly process any deferred payloads
428
-
429
- incrementalPlaceholders.forEach(function (placeholder) {
430
- if (placeholder.kind === 'defer') {
431
- _this7._processDeferResponse(placeholder.label, placeholder.path, placeholder, {
432
- data: placeholder.data
433
- });
434
- }
612
+ if (moduleImportPayloads && moduleImportPayloads.length !== 0) {
613
+ var operationLoader = _this9._operationLoader;
614
+ !operationLoader ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected an operationLoader to be ' + 'configured when using `@match`.') : invariant(false) : void 0;
615
+ moduleImportPayloads.forEach(function (moduleImportPayload) {
616
+ _this9._processModuleImportPayload(moduleImportPayload, operationLoader);
435
617
  });
436
618
  }
437
- }
619
+
620
+ if (incrementalPlaceholders && incrementalPlaceholders.length !== 0) {
621
+ _this9._incrementalPayloadsPending = _this9._state !== 'loading_final';
622
+ incrementalPlaceholders.forEach(function (incrementalPlaceholder) {
623
+ _this9._processIncrementalPlaceholder(payload, incrementalPlaceholder);
624
+ });
625
+
626
+ if (_this9._isClientPayload || _this9._state === 'loading_final') {
627
+ // The query has defer/stream selections that are enabled, but either
628
+ // the server indicated that this is a "final" payload: no incremental
629
+ // payloads will be delivered, then warn that the query was (likely)
630
+ // executed on the server in non-streaming mode, with incremental
631
+ // delivery disabled; or this is a client payload, and there will be
632
+ // no incremental payload.
633
+ process.env.NODE_ENV !== "production" ? warning(_this9._isClientPayload, 'RelayModernEnvironment: Operation `%s` contains @defer/@stream ' + 'directives but was executed in non-streaming mode. See ' + 'https://fburl.com/relay-incremental-delivery-non-streaming-warning.', _this9._operation.request.node.params.name) : void 0; // But eagerly process any deferred payloads
634
+
635
+ var relayPayloads = [];
636
+ incrementalPlaceholders.forEach(function (placeholder) {
637
+ if (placeholder.kind === 'defer') {
638
+ relayPayloads.push(_this9._processDeferResponse(placeholder.label, placeholder.path, placeholder, {
639
+ data: placeholder.data
640
+ }));
641
+ }
642
+ });
643
+
644
+ if (relayPayloads.length > 0) {
645
+ var updatedOwners = _this9._publishQueue.run();
646
+
647
+ _this9._updateOperationTracker(updatedOwners);
648
+
649
+ _this9._processPayloadFollowups(relayPayloads);
650
+ }
651
+ }
652
+ }
653
+ });
438
654
  };
439
655
 
440
656
  _proto._maybeCompleteSubscriptionOperationTracking = function _maybeCompleteSubscriptionOperationTracking() {
@@ -458,7 +674,7 @@ function () {
458
674
  ;
459
675
 
460
676
  _proto._processModuleImportPayload = function _processModuleImportPayload(moduleImportPayload, operationLoader) {
461
- var _this8 = this;
677
+ var _this10 = this;
462
678
 
463
679
  var syncOperation = operationLoader.get(moduleImportPayload.operationReference);
464
680
 
@@ -466,9 +682,9 @@ function () {
466
682
  // If the operation module is available synchronously, normalize the
467
683
  // data synchronously.
468
684
  this._schedule(function () {
469
- _this8._handleModuleImportPayload(moduleImportPayload, syncOperation);
685
+ _this10._handleModuleImportPayload(moduleImportPayload, syncOperation);
470
686
 
471
- _this8._maybeCompleteSubscriptionOperationTracking();
687
+ _this10._maybeCompleteSubscriptionOperationTracking();
472
688
  });
473
689
  } else {
474
690
  // Otherwise load the operation module and schedule a task to normalize
@@ -478,9 +694,9 @@ function () {
478
694
  this._pendingModulePayloadsCount++;
479
695
 
480
696
  var decrementPendingCount = function decrementPendingCount() {
481
- _this8._pendingModulePayloadsCount--;
697
+ _this10._pendingModulePayloadsCount--;
482
698
 
483
- _this8._maybeCompleteSubscriptionOperationTracking();
699
+ _this10._maybeCompleteSubscriptionOperationTracking();
484
700
  }; // Observable.from(operationLoader.load()) wouldn't catch synchronous
485
701
  // errors thrown by the load function, which is user-defined. Guard
486
702
  // against that with Observable.from(new Promise(<work>)).
@@ -490,37 +706,30 @@ function () {
490
706
  operationLoader.load(moduleImportPayload.operationReference).then(resolve, reject);
491
707
  })).map(function (operation) {
492
708
  if (operation != null) {
493
- _this8._schedule(function () {
494
- _this8._handleModuleImportPayload(moduleImportPayload, operation);
709
+ _this10._schedule(function () {
710
+ _this10._handleModuleImportPayload(moduleImportPayload, operation);
495
711
  });
496
712
  }
497
713
  }).subscribe({
498
714
  complete: function complete() {
499
- _this8._complete(_id3);
715
+ _this10._complete(_id3);
500
716
 
501
717
  decrementPendingCount();
502
718
  },
503
719
  error: function error(_error4) {
504
- _this8._error(_error4);
720
+ _this10._error(_error4);
505
721
 
506
722
  decrementPendingCount();
507
723
  },
508
724
  start: function start(subscription) {
509
- return _this8._start(_id3, subscription);
725
+ return _this10._start(_id3, subscription);
510
726
  }
511
727
  });
512
728
  }
513
729
  };
514
730
 
515
731
  _proto._handleModuleImportPayload = function _handleModuleImportPayload(moduleImportPayload, operation) {
516
- var selector = createNormalizationSelector(operation, moduleImportPayload.dataID, moduleImportPayload.variables);
517
- var relayPayload = normalizeResponse({
518
- data: moduleImportPayload.data
519
- }, selector, moduleImportPayload.typeName, {
520
- getDataID: this._getDataID,
521
- path: moduleImportPayload.path,
522
- request: this._operation.request
523
- });
732
+ var relayPayload = this._normalizeModuleImport(moduleImportPayload, operation);
524
733
 
525
734
  this._publishQueue.commitPayload(this._operation, relayPayload);
526
735
 
@@ -528,7 +737,7 @@ function () {
528
737
 
529
738
  this._updateOperationTracker(updatedOwners);
530
739
 
531
- this._processPayloadFollowups(relayPayload);
740
+ this._processPayloadFollowups([relayPayload]);
532
741
  }
533
742
  /**
534
743
  * The executor now knows that GraphQL responses are expected for a given
@@ -544,7 +753,7 @@ function () {
544
753
  ;
545
754
 
546
755
  _proto._processIncrementalPlaceholder = function _processIncrementalPlaceholder(relayPayload, placeholder) {
547
- var _this9 = this;
756
+ var _this11 = this;
548
757
 
549
758
  var _relayPayload$fieldPa;
550
759
 
@@ -572,9 +781,9 @@ function () {
572
781
 
573
782
  var parentID;
574
783
 
575
- if (placeholder.kind === 'stream' || placeholder.kind === 'connection_edge') {
784
+ if (placeholder.kind === 'stream') {
576
785
  parentID = placeholder.parentID;
577
- } else if (placeholder.kind === 'defer' || placeholder.kind === 'connection_page_info') {
786
+ } else if (placeholder.kind === 'defer') {
578
787
  parentID = placeholder.selector.dataID;
579
788
  } else {
580
789
  placeholder;
@@ -625,10 +834,14 @@ function () {
625
834
 
626
835
 
627
836
  if (pendingResponses != null) {
628
- pendingResponses.forEach(function (incrementalResponse) {
629
- _this9._schedule(function () {
630
- _this9._processIncrementalResponse(incrementalResponse);
631
- });
837
+ this._schedule(function () {
838
+ var payloadFollowups = _this11._processIncrementalResponses(pendingResponses);
839
+
840
+ var updatedOwners = _this11._publishQueue.run();
841
+
842
+ _this11._updateOperationTracker(updatedOwners);
843
+
844
+ _this11._processPayloadFollowups(payloadFollowups);
632
845
  });
633
846
  }
634
847
  }
@@ -639,131 +852,70 @@ function () {
639
852
  */
640
853
  ;
641
854
 
642
- _proto._processIncrementalResponse = function _processIncrementalResponse(incrementalResponse) {
643
- var label = incrementalResponse.label,
644
- path = incrementalResponse.path,
645
- response = incrementalResponse.response;
855
+ _proto._processIncrementalResponses = function _processIncrementalResponses(incrementalResponses) {
856
+ var _this12 = this;
646
857
 
647
- var resultForLabel = this._incrementalResults.get(label);
858
+ var relayPayloads = [];
859
+ incrementalResponses.forEach(function (incrementalResponse) {
860
+ var label = incrementalResponse.label,
861
+ path = incrementalResponse.path,
862
+ response = incrementalResponse.response;
648
863
 
649
- if (resultForLabel == null) {
650
- resultForLabel = new Map();
864
+ var resultForLabel = _this12._incrementalResults.get(label);
651
865
 
652
- this._incrementalResults.set(label, resultForLabel);
653
- }
866
+ if (resultForLabel == null) {
867
+ resultForLabel = new Map();
654
868
 
655
- if (label.indexOf('$defer$') !== -1) {
656
- var pathKey = path.map(String).join('.');
657
- var resultForPath = resultForLabel.get(pathKey);
658
-
659
- if (resultForPath == null) {
660
- resultForPath = {
661
- kind: 'response',
662
- responses: [incrementalResponse]
663
- };
664
- resultForLabel.set(pathKey, resultForPath);
665
- return;
666
- } else if (resultForPath.kind === 'response') {
667
- resultForPath.responses.push(incrementalResponse);
668
- return;
869
+ _this12._incrementalResults.set(label, resultForLabel);
669
870
  }
670
871
 
671
- var placeholder = resultForPath.placeholder;
872
+ if (label.indexOf('$defer$') !== -1) {
873
+ var pathKey = path.map(String).join('.');
874
+ var resultForPath = resultForLabel.get(pathKey);
875
+
876
+ if (resultForPath == null) {
877
+ resultForPath = {
878
+ kind: 'response',
879
+ responses: [incrementalResponse]
880
+ };
881
+ resultForLabel.set(pathKey, resultForPath);
882
+ return;
883
+ } else if (resultForPath.kind === 'response') {
884
+ resultForPath.responses.push(incrementalResponse);
885
+ return;
886
+ }
672
887
 
673
- if (placeholder.kind === 'connection_page_info') {
674
- this._processConnectionPageInfoResponse(label, path, placeholder, response);
675
- } else {
888
+ var placeholder = resultForPath.placeholder;
676
889
  !(placeholder.kind === 'defer') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected data for path `%s` for label `%s` ' + 'to be data for @defer, was `@%s`.', pathKey, label, placeholder.kind) : invariant(false) : void 0;
677
-
678
- this._processDeferResponse(label, path, placeholder, response);
679
- }
680
- } else {
681
- // @stream payload path values end in the field name and item index,
682
- // but Relay records paths relative to the parent of the stream node:
683
- // therefore we strip the last two elements just to lookup the path
684
- // (the item index is used later to insert the element in the list)
685
- var _pathKey = path.slice(0, -2).map(String).join('.');
686
-
687
- var _resultForPath = resultForLabel.get(_pathKey);
688
-
689
- if (_resultForPath == null) {
690
- _resultForPath = {
691
- kind: 'response',
692
- responses: [incrementalResponse]
693
- };
694
- resultForLabel.set(_pathKey, _resultForPath);
695
- return;
696
- } else if (_resultForPath.kind === 'response') {
697
- _resultForPath.responses.push(incrementalResponse);
698
-
699
- return;
700
- }
701
-
702
- var _placeholder = _resultForPath.placeholder;
703
-
704
- if (_placeholder.kind === 'connection_edge') {
705
- this._processConnectionEdgeResponse(label, path, _placeholder, response);
890
+ relayPayloads.push(_this12._processDeferResponse(label, path, placeholder, response));
706
891
  } else {
707
- !(_placeholder.kind === 'stream') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected data for path `%s` for label `%s` ' + 'to be data for @stream, was `@%s`.', _pathKey, label, _placeholder.kind) : invariant(false) : void 0;
892
+ // @stream payload path values end in the field name and item index,
893
+ // but Relay records paths relative to the parent of the stream node:
894
+ // therefore we strip the last two elements just to lookup the path
895
+ // (the item index is used later to insert the element in the list)
896
+ var _pathKey = path.slice(0, -2).map(String).join('.');
897
+
898
+ var _resultForPath = resultForLabel.get(_pathKey);
899
+
900
+ if (_resultForPath == null) {
901
+ _resultForPath = {
902
+ kind: 'response',
903
+ responses: [incrementalResponse]
904
+ };
905
+ resultForLabel.set(_pathKey, _resultForPath);
906
+ return;
907
+ } else if (_resultForPath.kind === 'response') {
908
+ _resultForPath.responses.push(incrementalResponse);
909
+
910
+ return;
911
+ }
708
912
 
709
- this._processStreamResponse(label, path, _placeholder, response);
913
+ var _placeholder = _resultForPath.placeholder;
914
+ !(_placeholder.kind === 'stream') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected data for path `%s` for label `%s` ' + 'to be data for @stream, was `@%s`.', _pathKey, label, _placeholder.kind) : invariant(false) : void 0;
915
+ relayPayloads.push(_this12._processStreamResponse(label, path, _placeholder, response));
710
916
  }
711
- }
712
- };
713
-
714
- _proto._processConnectionPageInfoResponse = function _processConnectionPageInfoResponse(label, path, placeholder, response) {
715
- var _relayPayload$connect;
716
-
717
- var relayPayload = normalizeResponse(response, placeholder.selector, placeholder.typeName, {
718
- getDataID: this._getDataID,
719
- path: placeholder.path,
720
- request: this._operation.request
721
917
  });
722
-
723
- var _RelayConnectionInter = RelayConnectionInterface.get(),
724
- END_CURSOR = _RelayConnectionInter.END_CURSOR,
725
- HAS_NEXT_PAGE = _RelayConnectionInter.HAS_NEXT_PAGE,
726
- HAS_PREV_PAGE = _RelayConnectionInter.HAS_PREV_PAGE,
727
- PAGE_INFO = _RelayConnectionInter.PAGE_INFO,
728
- START_CURSOR = _RelayConnectionInter.START_CURSOR;
729
-
730
- var pageRecord = relayPayload.source.get(placeholder.selector.dataID);
731
- var pageInfoID = pageRecord != null ? RelayModernRecord.getLinkedRecordID(pageRecord, PAGE_INFO) : null;
732
- var pageInfoRecord = pageInfoID != null ? relayPayload.source.get(pageInfoID) : null;
733
- var endCursor;
734
- var hasNextPage;
735
- var hasPrevPage;
736
- var startCursor;
737
-
738
- if (pageInfoRecord != null) {
739
- endCursor = RelayModernRecord.getValue(pageInfoRecord, END_CURSOR);
740
- hasNextPage = RelayModernRecord.getValue(pageInfoRecord, HAS_NEXT_PAGE);
741
- hasPrevPage = RelayModernRecord.getValue(pageInfoRecord, HAS_PREV_PAGE);
742
- startCursor = RelayModernRecord.getValue(pageInfoRecord, START_CURSOR);
743
- }
744
-
745
- relayPayload = (0, _objectSpread2["default"])({}, relayPayload, {
746
- connectionEvents: ((_relayPayload$connect = relayPayload.connectionEvents) !== null && _relayPayload$connect !== void 0 ? _relayPayload$connect : []).concat({
747
- kind: 'stream.pageInfo',
748
- args: placeholder.args,
749
- connectionID: placeholder.connectionID,
750
- pageInfo: {
751
- endCursor: typeof endCursor === 'string' ? endCursor : null,
752
- startCursor: typeof startCursor === 'string' ? startCursor : null,
753
- hasNextPage: typeof hasNextPage === 'boolean' ? hasNextPage : null,
754
- hasPrevPage: typeof hasPrevPage === 'boolean' ? hasPrevPage : null
755
- },
756
- request: this._operation.request
757
- })
758
- });
759
-
760
- this._publishQueue.commitPayload(this._operation, relayPayload);
761
-
762
- var updatedOwners = this._publishQueue.run();
763
-
764
- this._updateOperationTracker(updatedOwners);
765
-
766
- this._processPayloadFollowups(relayPayload);
918
+ return relayPayloads;
767
919
  };
768
920
 
769
921
  _proto._processDeferResponse = function _processDeferResponse(label, path, placeholder, response) {
@@ -771,7 +923,8 @@ function () {
771
923
  var relayPayload = normalizeResponse(response, placeholder.selector, placeholder.typeName, {
772
924
  getDataID: this._getDataID,
773
925
  path: placeholder.path,
774
- request: this._operation.request
926
+ request: this._operation.request,
927
+ treatMissingFieldsAsNull: this._treatMissingFieldsAsNull
775
928
  });
776
929
 
777
930
  this._publishQueue.commitPayload(this._operation, relayPayload); // Load the version of the parent record from which this incremental data
@@ -784,55 +937,21 @@ function () {
784
937
  var fieldPayloads = parentEntry.fieldPayloads;
785
938
 
786
939
  if (fieldPayloads.length !== 0) {
940
+ var _response$extensions2;
941
+
787
942
  var handleFieldsRelayPayload = {
788
- connectionEvents: null,
789
943
  errors: null,
790
944
  fieldPayloads: fieldPayloads,
791
945
  incrementalPlaceholders: null,
792
946
  moduleImportPayloads: null,
793
- source: RelayRecordSource.create()
947
+ source: RelayRecordSource.create(),
948
+ isFinal: ((_response$extensions2 = response.extensions) === null || _response$extensions2 === void 0 ? void 0 : _response$extensions2.is_final) === true
794
949
  };
795
950
 
796
951
  this._publishQueue.commitPayload(this._operation, handleFieldsRelayPayload);
797
952
  }
798
953
 
799
- var updatedOwners = this._publishQueue.run();
800
-
801
- this._updateOperationTracker(updatedOwners);
802
-
803
- this._processPayloadFollowups(relayPayload);
804
- };
805
-
806
- _proto._processConnectionEdgeResponse = function _processConnectionEdgeResponse(label, path, placeholder, response) {
807
- var _relayPayload$connect2;
808
-
809
- var parentID = placeholder.parentID,
810
- node = placeholder.node,
811
- variables = placeholder.variables;
812
-
813
- var _this$_normalizeStrea = this._normalizeStreamItem(response, parentID, node, variables, path, placeholder.path),
814
- relayPayload = _this$_normalizeStrea.relayPayload,
815
- itemID = _this$_normalizeStrea.itemID,
816
- itemIndex = _this$_normalizeStrea.itemIndex;
817
-
818
- relayPayload = (0, _objectSpread2["default"])({}, relayPayload, {
819
- connectionEvents: ((_relayPayload$connect2 = relayPayload.connectionEvents) !== null && _relayPayload$connect2 !== void 0 ? _relayPayload$connect2 : []).concat({
820
- kind: 'stream.edge',
821
- args: placeholder.args,
822
- connectionID: placeholder.connectionID,
823
- edgeID: itemID,
824
- index: itemIndex,
825
- request: this._operation.request
826
- })
827
- });
828
-
829
- this._publishQueue.commitPayload(this._operation, relayPayload);
830
-
831
- var updatedOwners = this._publishQueue.run();
832
-
833
- this._updateOperationTracker(updatedOwners);
834
-
835
- this._processPayloadFollowups(relayPayload);
954
+ return relayPayload;
836
955
  }
837
956
  /**
838
957
  * Process the data for one item in a @stream field.
@@ -847,13 +966,13 @@ function () {
847
966
  var field = node.selections[0];
848
967
  !(field != null && field.kind === 'LinkedField' && field.plural === true) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected @stream to be used on a plural field.') : invariant(false) : void 0;
849
968
 
850
- var _this$_normalizeStrea2 = this._normalizeStreamItem(response, parentID, field, variables, path, placeholder.path),
851
- fieldPayloads = _this$_normalizeStrea2.fieldPayloads,
852
- itemID = _this$_normalizeStrea2.itemID,
853
- itemIndex = _this$_normalizeStrea2.itemIndex,
854
- prevIDs = _this$_normalizeStrea2.prevIDs,
855
- relayPayload = _this$_normalizeStrea2.relayPayload,
856
- storageKey = _this$_normalizeStrea2.storageKey; // Publish the new item and update the parent record to set
969
+ var _this$_normalizeStrea = this._normalizeStreamItem(response, parentID, field, variables, path, placeholder.path),
970
+ fieldPayloads = _this$_normalizeStrea.fieldPayloads,
971
+ itemID = _this$_normalizeStrea.itemID,
972
+ itemIndex = _this$_normalizeStrea.itemIndex,
973
+ prevIDs = _this$_normalizeStrea.prevIDs,
974
+ relayPayload = _this$_normalizeStrea.relayPayload,
975
+ storageKey = _this$_normalizeStrea.storageKey; // Publish the new item and update the parent record to set
857
976
  // field[index] = item *if* the parent record hasn't been concurrently
858
977
  // modified.
859
978
 
@@ -892,22 +1011,18 @@ function () {
892
1011
 
893
1012
  if (fieldPayloads.length !== 0) {
894
1013
  var handleFieldsRelayPayload = {
895
- connectionEvents: null,
896
1014
  errors: null,
897
1015
  fieldPayloads: fieldPayloads,
898
1016
  incrementalPlaceholders: null,
899
1017
  moduleImportPayloads: null,
900
- source: RelayRecordSource.create()
1018
+ source: RelayRecordSource.create(),
1019
+ isFinal: false
901
1020
  };
902
1021
 
903
1022
  this._publishQueue.commitPayload(this._operation, handleFieldsRelayPayload);
904
1023
  }
905
1024
 
906
- var updatedOwners = this._publishQueue.run();
907
-
908
- this._updateOperationTracker(updatedOwners);
909
-
910
- this._processPayloadFollowups(relayPayload);
1025
+ return relayPayload;
911
1026
  };
912
1027
 
913
1028
  _proto._normalizeStreamItem = function _normalizeStreamItem(response, parentID, field, variables, path, normalizationPath) {
@@ -960,7 +1075,8 @@ function () {
960
1075
  var relayPayload = normalizeResponse(response, selector, typeName, {
961
1076
  getDataID: this._getDataID,
962
1077
  path: [].concat((0, _toConsumableArray2["default"])(normalizationPath), [responseKey, String(itemIndex)]),
963
- request: this._operation.request
1078
+ request: this._operation.request,
1079
+ treatMissingFieldsAsNull: this._treatMissingFieldsAsNull
964
1080
  });
965
1081
  return {
966
1082
  fieldPayloads: fieldPayloads,
@@ -987,15 +1103,42 @@ function () {
987
1103
  return Executor;
988
1104
  }();
989
1105
 
1106
+ function partitionGraphQLResponses(responses) {
1107
+ var nonIncrementalResponses = [];
1108
+ var incrementalResponses = [];
1109
+ responses.forEach(function (response) {
1110
+ if (response.path != null || response.label != null) {
1111
+ var label = response.label,
1112
+ path = response.path;
1113
+
1114
+ if (label == null || path == null) {
1115
+ !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernQueryExecutor: invalid incremental payload, expected ' + '`path` and `label` to either both be null/undefined, or ' + '`path` to be an `Array<string | number>` and `label` to be a ' + '`string`.') : invariant(false) : void 0;
1116
+ }
1117
+
1118
+ incrementalResponses.push({
1119
+ label: label,
1120
+ path: path,
1121
+ response: response
1122
+ });
1123
+ } else {
1124
+ nonIncrementalResponses.push(response);
1125
+ }
1126
+ });
1127
+ return [nonIncrementalResponses, incrementalResponses];
1128
+ }
1129
+
990
1130
  function normalizeResponse(response, selector, typeName, options) {
1131
+ var _response$extensions3;
1132
+
991
1133
  var data = response.data,
992
1134
  errors = response.errors;
993
1135
  var source = RelayRecordSource.create();
994
1136
  var record = RelayModernRecord.create(selector.dataID, typeName);
995
1137
  source.set(selector.dataID, record);
996
1138
  var relayPayload = RelayResponseNormalizer.normalize(source, selector, data, options);
997
- return (0, _objectSpread2["default"])({}, relayPayload, {
998
- errors: errors
1139
+ return _objectSpread({}, relayPayload, {
1140
+ errors: errors,
1141
+ isFinal: ((_response$extensions3 = response.extensions) === null || _response$extensions3 === void 0 ? void 0 : _response$extensions3.is_final) === true
999
1142
  });
1000
1143
  }
1001
1144