relay-runtime 8.0.0 → 10.0.1

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 (135) hide show
  1. package/handlers/RelayDefaultHandlerProvider.js.flow +41 -0
  2. package/handlers/connection/ConnectionHandler.js.flow +549 -0
  3. package/handlers/connection/ConnectionInterface.js.flow +92 -0
  4. package/handlers/connection/MutationHandlers.js.flow +88 -0
  5. package/index.js +1 -1
  6. package/index.js.flow +320 -0
  7. package/lib/handlers/RelayDefaultHandlerProvider.js +13 -2
  8. package/lib/handlers/connection/{RelayConnectionHandler.js → ConnectionHandler.js} +33 -35
  9. package/lib/handlers/connection/{RelayConnectionInterface.js → ConnectionInterface.js} +2 -2
  10. package/lib/handlers/connection/MutationHandlers.js +86 -0
  11. package/lib/index.js +15 -19
  12. package/lib/mutations/RelayDeclarativeMutationConfig.js +29 -52
  13. package/lib/mutations/RelayRecordProxy.js +1 -3
  14. package/lib/mutations/RelayRecordSourceMutator.js +2 -9
  15. package/lib/mutations/RelayRecordSourceProxy.js +2 -4
  16. package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -13
  17. package/lib/mutations/commitMutation.js +13 -3
  18. package/lib/mutations/validateMutation.js +16 -9
  19. package/lib/network/RelayObservable.js +9 -9
  20. package/lib/network/RelayQueryResponseCache.js +8 -6
  21. package/lib/query/PreloadableQueryRegistry.js +70 -0
  22. package/lib/query/fetchQueryInternal.js +31 -23
  23. package/lib/store/DataChecker.js +122 -110
  24. package/lib/store/RelayConcreteVariables.js +6 -2
  25. package/lib/store/RelayModernEnvironment.js +121 -67
  26. package/lib/store/RelayModernFragmentSpecResolver.js +12 -16
  27. package/lib/store/RelayModernQueryExecutor.js +389 -314
  28. package/lib/store/RelayModernRecord.js +14 -9
  29. package/lib/store/RelayModernSelector.js +7 -3
  30. package/lib/store/RelayModernStore.js +289 -484
  31. package/lib/store/RelayOperationTracker.js +35 -78
  32. package/lib/store/RelayOptimisticRecordSource.js +7 -5
  33. package/lib/store/RelayPublishQueue.js +6 -33
  34. package/lib/store/RelayReader.js +113 -45
  35. package/lib/store/RelayRecordSource.js +2 -9
  36. package/lib/store/RelayRecordSourceMapImpl.js +13 -18
  37. package/lib/store/RelayReferenceMarker.js +40 -60
  38. package/lib/store/RelayResponseNormalizer.js +158 -193
  39. package/lib/store/RelayStoreUtils.js +1 -0
  40. package/lib/store/StoreInspector.js +8 -8
  41. package/lib/store/TypeID.js +28 -0
  42. package/lib/store/cloneRelayScalarHandleSourceField.js +44 -0
  43. package/lib/store/normalizeRelayPayload.js +6 -2
  44. package/lib/store/readInlineData.js +1 -1
  45. package/lib/subscription/requestSubscription.js +5 -3
  46. package/lib/util/RelayConcreteNode.js +9 -6
  47. package/lib/util/RelayError.js +39 -9
  48. package/lib/util/RelayFeatureFlags.js +2 -5
  49. package/lib/util/RelayReplaySubject.js +3 -3
  50. package/lib/util/createPayloadFor3DField.js +7 -2
  51. package/lib/util/getRequestIdentifier.js +2 -2
  52. package/lib/util/recycleNodesInto.js +2 -6
  53. package/mutations/RelayDeclarativeMutationConfig.js.flow +380 -0
  54. package/mutations/RelayRecordProxy.js.flow +165 -0
  55. package/mutations/RelayRecordSourceMutator.js.flow +238 -0
  56. package/mutations/RelayRecordSourceProxy.js.flow +164 -0
  57. package/mutations/RelayRecordSourceSelectorProxy.js.flow +119 -0
  58. package/mutations/applyOptimisticMutation.js.flow +76 -0
  59. package/mutations/commitLocalUpdate.js.flow +24 -0
  60. package/mutations/commitMutation.js.flow +182 -0
  61. package/mutations/validateMutation.js.flow +213 -0
  62. package/network/ConvertToExecuteFunction.js.flow +49 -0
  63. package/network/RelayNetwork.js.flow +84 -0
  64. package/network/RelayNetworkTypes.js.flow +123 -0
  65. package/network/RelayObservable.js.flow +634 -0
  66. package/network/RelayQueryResponseCache.js.flow +111 -0
  67. package/package.json +1 -1
  68. package/query/GraphQLTag.js.flow +166 -0
  69. package/query/PreloadableQueryRegistry.js.flow +65 -0
  70. package/query/fetchQuery.js.flow +47 -0
  71. package/query/fetchQueryInternal.js.flow +348 -0
  72. package/relay-runtime.js +2 -2
  73. package/relay-runtime.min.js +2 -2
  74. package/store/ClientID.js.flow +43 -0
  75. package/store/DataChecker.js.flow +502 -0
  76. package/store/RelayConcreteVariables.js.flow +96 -0
  77. package/store/RelayModernEnvironment.js.flow +551 -0
  78. package/store/RelayModernFragmentSpecResolver.js.flow +426 -0
  79. package/store/RelayModernOperationDescriptor.js.flow +88 -0
  80. package/store/RelayModernQueryExecutor.js.flow +1321 -0
  81. package/store/RelayModernRecord.js.flow +403 -0
  82. package/store/RelayModernSelector.js.flow +455 -0
  83. package/store/RelayModernStore.js.flow +842 -0
  84. package/store/RelayOperationTracker.js.flow +164 -0
  85. package/store/RelayOptimisticRecordSource.js.flow +119 -0
  86. package/store/RelayPublishQueue.js.flow +401 -0
  87. package/store/RelayReader.js.flow +473 -0
  88. package/store/RelayRecordSource.js.flow +29 -0
  89. package/store/RelayRecordSourceMapImpl.js.flow +87 -0
  90. package/store/RelayRecordState.js.flow +37 -0
  91. package/store/RelayReferenceMarker.js.flow +257 -0
  92. package/store/RelayResponseNormalizer.js.flow +680 -0
  93. package/store/RelayStoreTypes.js.flow +899 -0
  94. package/store/RelayStoreUtils.js.flow +219 -0
  95. package/store/StoreInspector.js.flow +171 -0
  96. package/store/TypeID.js.flow +28 -0
  97. package/store/ViewerPattern.js.flow +26 -0
  98. package/store/cloneRelayHandleSourceField.js.flow +66 -0
  99. package/store/cloneRelayScalarHandleSourceField.js.flow +62 -0
  100. package/store/createFragmentSpecResolver.js.flow +55 -0
  101. package/store/createRelayContext.js.flow +44 -0
  102. package/store/defaultGetDataID.js.flow +27 -0
  103. package/store/hasOverlappingIDs.js.flow +34 -0
  104. package/store/isRelayModernEnvironment.js.flow +27 -0
  105. package/store/normalizeRelayPayload.js.flow +51 -0
  106. package/store/readInlineData.js.flow +75 -0
  107. package/subscription/requestSubscription.js.flow +100 -0
  108. package/util/JSResourceTypes.flow.js.flow +20 -0
  109. package/util/NormalizationNode.js.flow +198 -0
  110. package/util/ReaderNode.js.flow +208 -0
  111. package/util/RelayConcreteNode.js.flow +93 -0
  112. package/util/RelayDefaultHandleKey.js.flow +17 -0
  113. package/util/RelayError.js.flow +62 -0
  114. package/util/RelayFeatureFlags.js.flow +30 -0
  115. package/util/RelayProfiler.js.flow +284 -0
  116. package/util/RelayReplaySubject.js.flow +135 -0
  117. package/util/RelayRuntimeTypes.js.flow +72 -0
  118. package/util/createPayloadFor3DField.js.flow +43 -0
  119. package/util/deepFreeze.js.flow +36 -0
  120. package/util/generateID.js.flow +21 -0
  121. package/util/getFragmentIdentifier.js.flow +52 -0
  122. package/util/getRelayHandleKey.js.flow +41 -0
  123. package/util/getRequestIdentifier.js.flow +42 -0
  124. package/util/isPromise.js.flow +21 -0
  125. package/util/isScalarAndEqual.js.flow +26 -0
  126. package/util/recycleNodesInto.js.flow +76 -0
  127. package/util/resolveImmediate.js.flow +30 -0
  128. package/util/stableCopy.js.flow +35 -0
  129. package/lib/handlers/RelayDefaultMissingFieldHandlers.js +0 -26
  130. package/lib/handlers/getRelayDefaultMissingFieldHandlers.js +0 -36
  131. package/lib/query/RelayModernGraphQLTag.js +0 -104
  132. package/lib/store/RelayConnection.js +0 -37
  133. package/lib/store/RelayConnectionResolver.js +0 -178
  134. package/lib/store/RelayRecordSourceObjectImpl.js +0 -79
  135. package/lib/util/getFragmentSpecIdentifier.js +0 -27
@@ -14,9 +14,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
14
14
 
15
15
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
16
16
 
17
- var RelayConnection = require('./RelayConnection');
18
-
19
- var RelayConnectionInterface = require('../handlers/connection/RelayConnectionInterface');
17
+ var RelayFeatureFlags = require('../util/RelayFeatureFlags');
20
18
 
21
19
  var RelayModernRecord = require('./RelayModernRecord');
22
20
 
@@ -30,14 +28,14 @@ var _require = require('../util/RelayConcreteNode'),
30
28
  CONDITION = _require.CONDITION,
31
29
  CLIENT_EXTENSION = _require.CLIENT_EXTENSION,
32
30
  DEFER = _require.DEFER,
33
- CONNECTION = _require.CONNECTION,
34
31
  INLINE_FRAGMENT = _require.INLINE_FRAGMENT,
35
32
  LINKED_FIELD = _require.LINKED_FIELD,
36
33
  LINKED_HANDLE = _require.LINKED_HANDLE,
37
34
  MODULE_IMPORT = _require.MODULE_IMPORT,
38
35
  SCALAR_FIELD = _require.SCALAR_FIELD,
39
36
  SCALAR_HANDLE = _require.SCALAR_HANDLE,
40
- STREAM = _require.STREAM;
37
+ STREAM = _require.STREAM,
38
+ TYPE_DISCRIMINATOR = _require.TYPE_DISCRIMINATOR;
41
39
 
42
40
  var _require2 = require('./ClientID'),
43
41
  generateClientID = _require2.generateClientID,
@@ -47,14 +45,17 @@ var _require3 = require('./RelayModernSelector'),
47
45
  createNormalizationSelector = _require3.createNormalizationSelector;
48
46
 
49
47
  var _require4 = require('./RelayStoreUtils'),
50
- formatStorageKey = _require4.formatStorageKey,
51
- getArgumentValue = _require4.getArgumentValue,
52
48
  getArgumentValues = _require4.getArgumentValues,
53
49
  getHandleStorageKey = _require4.getHandleStorageKey,
54
50
  getModuleComponentKey = _require4.getModuleComponentKey,
55
51
  getModuleOperationKey = _require4.getModuleOperationKey,
56
52
  getStorageKey = _require4.getStorageKey,
57
- TYPENAME_KEY = _require4.TYPENAME_KEY;
53
+ TYPENAME_KEY = _require4.TYPENAME_KEY,
54
+ ROOT_ID = _require4.ROOT_ID;
55
+
56
+ var _require5 = require('./TypeID'),
57
+ generateTypeID = _require5.generateTypeID,
58
+ TYPE_SCHEMA_TYPE = _require5.TYPE_SCHEMA_TYPE;
58
59
 
59
60
  /**
60
61
  * Normalizes the results of a query and standard GraphQL response, writing the
@@ -74,19 +75,17 @@ function normalize(recordSource, selector, response, options) {
74
75
  */
75
76
 
76
77
 
77
- var RelayResponseNormalizer =
78
- /*#__PURE__*/
79
- function () {
78
+ var RelayResponseNormalizer = /*#__PURE__*/function () {
80
79
  function RelayResponseNormalizer(recordSource, variables, options) {
81
- this._connectionEvents = [];
82
80
  this._getDataId = options.getDataID;
83
81
  this._handleFieldPayloads = [];
82
+ this._treatMissingFieldsAsNull = options.treatMissingFieldsAsNull;
84
83
  this._incrementalPlaceholders = [];
85
84
  this._isClientExtension = false;
85
+ this._isUnmatchedAbstractType = false;
86
86
  this._moduleImportPayloads = [];
87
87
  this._path = options.path ? (0, _toConsumableArray2["default"])(options.path) : [];
88
88
  this._recordSource = recordSource;
89
- this._request = options.request;
90
89
  this._variables = variables;
91
90
  }
92
91
 
@@ -100,12 +99,12 @@ function () {
100
99
  this._traverseSelections(node, record, data);
101
100
 
102
101
  return {
103
- connectionEvents: this._connectionEvents,
104
102
  errors: null,
105
103
  fieldPayloads: this._handleFieldPayloads,
106
104
  incrementalPlaceholders: this._incrementalPlaceholders,
107
105
  moduleImportPayloads: this._moduleImportPayloads,
108
- source: this._recordSource
106
+ source: this._recordSource,
107
+ isFinal: false
109
108
  };
110
109
  };
111
110
 
@@ -141,13 +140,76 @@ function () {
141
140
  break;
142
141
 
143
142
  case INLINE_FRAGMENT:
144
- var _typeName = RelayModernRecord.getType(record);
143
+ {
144
+ var abstractKey = selection.abstractKey;
145
145
 
146
- if (_typeName === selection.type) {
147
- this._traverseSelections(selection, record, data);
146
+ if (abstractKey == null) {
147
+ var _typeName = RelayModernRecord.getType(record);
148
+
149
+ if (_typeName === selection.type) {
150
+ this._traverseSelections(selection, record, data);
151
+ }
152
+ } else if (RelayFeatureFlags.ENABLE_PRECISE_TYPE_REFINEMENT) {
153
+ var implementsInterface = data.hasOwnProperty(abstractKey);
154
+
155
+ var _typeName2 = RelayModernRecord.getType(record);
156
+
157
+ var typeID = generateTypeID(_typeName2);
158
+
159
+ var typeRecord = this._recordSource.get(typeID);
160
+
161
+ if (typeRecord == null) {
162
+ typeRecord = RelayModernRecord.create(typeID, TYPE_SCHEMA_TYPE);
163
+
164
+ this._recordSource.set(typeID, typeRecord);
165
+ }
166
+
167
+ RelayModernRecord.setValue(typeRecord, abstractKey, implementsInterface);
168
+
169
+ if (implementsInterface) {
170
+ this._traverseSelections(selection, record, data);
171
+ }
172
+ } else {
173
+ // legacy behavior for abstract refinements: always normalize even
174
+ // if the type doesn't conform, but track if the type matches or not
175
+ // for determining whether response fields are expected to be present
176
+ var _implementsInterface = data.hasOwnProperty(abstractKey);
177
+
178
+ var parentIsUnmatchedAbstractType = this._isUnmatchedAbstractType;
179
+ this._isUnmatchedAbstractType = this._isUnmatchedAbstractType || !_implementsInterface;
180
+
181
+ this._traverseSelections(selection, record, data);
182
+
183
+ this._isUnmatchedAbstractType = parentIsUnmatchedAbstractType;
184
+ }
185
+
186
+ break;
148
187
  }
149
188
 
150
- break;
189
+ case TYPE_DISCRIMINATOR:
190
+ {
191
+ if (RelayFeatureFlags.ENABLE_PRECISE_TYPE_REFINEMENT) {
192
+ var _abstractKey = selection.abstractKey;
193
+
194
+ var _implementsInterface2 = data.hasOwnProperty(_abstractKey);
195
+
196
+ var _typeName3 = RelayModernRecord.getType(record);
197
+
198
+ var _typeID = generateTypeID(_typeName3);
199
+
200
+ var _typeRecord = this._recordSource.get(_typeID);
201
+
202
+ if (_typeRecord == null) {
203
+ _typeRecord = RelayModernRecord.create(_typeID, TYPE_SCHEMA_TYPE);
204
+
205
+ this._recordSource.set(_typeID, _typeRecord);
206
+ }
207
+
208
+ RelayModernRecord.setValue(_typeRecord, _abstractKey, _implementsInterface2);
209
+ }
210
+
211
+ break;
212
+ }
151
213
 
152
214
  case LINKED_HANDLE:
153
215
  case SCALAR_HANDLE:
@@ -160,7 +222,8 @@ function () {
160
222
  dataID: RelayModernRecord.getDataID(record),
161
223
  fieldKey: fieldKey,
162
224
  handle: selection.handle,
163
- handleKey: handleKey
225
+ handleKey: handleKey,
226
+ handleArgs: selection.handleArgs ? getArgumentValues(selection.handleArgs, this._variables) : {}
164
227
  });
165
228
 
166
229
  break;
@@ -189,11 +252,6 @@ function () {
189
252
  this._isClientExtension = isClientExtension;
190
253
  break;
191
254
 
192
- case CONNECTION:
193
- this._normalizeConnection(node, selection, record, data);
194
-
195
- break;
196
-
197
255
  default:
198
256
  selection;
199
257
  !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer(): Unexpected ast kind `%s`.', selection.kind) : invariant(false) : void 0;
@@ -253,16 +311,14 @@ function () {
253
311
  };
254
312
 
255
313
  _proto._normalizeModuleImport = function _normalizeModuleImport(parent, moduleImport, record, data) {
256
- var _componentReference, _operationReference;
257
-
258
314
  !(typeof data === 'object' && data) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected data for @module to be an object.') : invariant(false) : void 0;
259
315
  var typeName = RelayModernRecord.getType(record);
260
316
  var componentKey = getModuleComponentKey(moduleImport.documentName);
261
317
  var componentReference = data[componentKey];
262
- RelayModernRecord.setValue(record, componentKey, (_componentReference = componentReference) !== null && _componentReference !== void 0 ? _componentReference : null);
318
+ RelayModernRecord.setValue(record, componentKey, componentReference !== null && componentReference !== void 0 ? componentReference : null);
263
319
  var operationKey = getModuleOperationKey(moduleImport.documentName);
264
320
  var operationReference = data[operationKey];
265
- RelayModernRecord.setValue(record, operationKey, (_operationReference = operationReference) !== null && _operationReference !== void 0 ? _operationReference : null);
321
+ RelayModernRecord.setValue(record, operationKey, operationReference !== null && operationReference !== void 0 ? operationReference : null);
266
322
 
267
323
  if (operationReference != null) {
268
324
  this._moduleImportPayloads.push({
@@ -274,122 +330,6 @@ function () {
274
330
  variables: this._variables
275
331
  });
276
332
  }
277
- }
278
- /**
279
- * Connections are represented in the AST as a LinkedField (with connection-
280
- * specific args like after/first stripped) that wraps any metadata fields
281
- * such as count, plus a Connection node that represents the page of data
282
- * being fetched (the edges + pageInfo). The outer LinkedField is normalized
283
- * like any other, and the Connection field is normalized by synthesizing
284
- * a record to represent the page that was fetched and normalizing the edges
285
- * and pageInfo into that page record - as well as recording a "fetch" event.
286
- */
287
- ;
288
-
289
- _proto._normalizeConnection = function _normalizeConnection(parent, selection, record, data) {
290
- // Normalize the data for the page
291
- var parentID = RelayModernRecord.getDataID(record);
292
- var args = selection.args != null ? getArgumentValues(selection.args, this._variables) : {};
293
- var pageStorageKey = formatStorageKey('__connection_page', args);
294
- var pageID = generateClientID(parentID, pageStorageKey);
295
-
296
- var pageRecord = this._recordSource.get(pageID);
297
-
298
- if (pageRecord == null) {
299
- pageRecord = RelayModernRecord.create(pageID, '__ConnectionPage');
300
-
301
- this._recordSource.set(pageID, pageRecord);
302
- }
303
-
304
- RelayModernRecord.setLinkedRecordID(record, pageStorageKey, pageID);
305
-
306
- this._normalizeField(parent, selection.edges, pageRecord, data);
307
-
308
- this._normalizeField(parent, selection.pageInfo, pageRecord, data); // Construct a "fetch" connection event
309
-
310
-
311
- var connectionID = RelayConnection.createConnectionID(parentID, selection.label);
312
-
313
- var _RelayConnectionInter = RelayConnectionInterface.get(),
314
- EDGES = _RelayConnectionInter.EDGES,
315
- END_CURSOR = _RelayConnectionInter.END_CURSOR,
316
- HAS_NEXT_PAGE = _RelayConnectionInter.HAS_NEXT_PAGE,
317
- HAS_PREV_PAGE = _RelayConnectionInter.HAS_PREV_PAGE,
318
- PAGE_INFO = _RelayConnectionInter.PAGE_INFO,
319
- START_CURSOR = _RelayConnectionInter.START_CURSOR;
320
-
321
- var edgeIDs = RelayModernRecord.getLinkedRecordIDs(pageRecord, EDGES);
322
-
323
- if (edgeIDs == null) {
324
- return;
325
- }
326
-
327
- var pageInfoID = RelayModernRecord.getLinkedRecordID(pageRecord, PAGE_INFO);
328
- var pageInfoRecord = pageInfoID != null ? this._recordSource.get(pageInfoID) : null;
329
- var endCursor;
330
- var hasNextPage;
331
- var hasPrevPage;
332
- var startCursor;
333
-
334
- if (pageInfoRecord != null) {
335
- endCursor = RelayModernRecord.getValue(pageInfoRecord, END_CURSOR);
336
- hasNextPage = RelayModernRecord.getValue(pageInfoRecord, HAS_NEXT_PAGE);
337
- hasPrevPage = RelayModernRecord.getValue(pageInfoRecord, HAS_PREV_PAGE);
338
- startCursor = RelayModernRecord.getValue(pageInfoRecord, START_CURSOR);
339
- } // If streaming is enabled, also emit incremental placeholders for the
340
- // edges and pageInfo
341
-
342
-
343
- var stream = selection.stream;
344
- var enableStream = stream != null ? getArgumentValue(stream["if"], this._variables) === true : false;
345
-
346
- if (stream != null && enableStream === true) {
347
- this._incrementalPlaceholders.push({
348
- kind: 'connection_edge',
349
- args: args,
350
- connectionID: connectionID,
351
- label: stream.streamLabel,
352
- path: (0, _toConsumableArray2["default"])(this._path),
353
- parentID: pageID,
354
- node: selection.edges,
355
- variables: this._variables
356
- });
357
-
358
- this._incrementalPlaceholders.push({
359
- kind: 'connection_page_info',
360
- args: args,
361
- connectionID: connectionID,
362
- data: data,
363
- label: stream.deferLabel,
364
- path: (0, _toConsumableArray2["default"])(this._path),
365
- selector: createNormalizationSelector({
366
- alias: null,
367
- args: null,
368
- concreteType: RelayModernRecord.getType(pageRecord),
369
- kind: 'LinkedField',
370
- name: '',
371
- plural: false,
372
- selections: [selection.pageInfo],
373
- storageKey: null
374
- }, pageID, this._variables),
375
- typeName: RelayModernRecord.getType(pageRecord)
376
- });
377
- }
378
-
379
- this._connectionEvents.push({
380
- kind: 'fetch',
381
- connectionID: connectionID,
382
- args: args,
383
- edgeIDs: edgeIDs,
384
- pageInfo: {
385
- endCursor: typeof endCursor === 'string' ? endCursor : null,
386
- startCursor: typeof startCursor === 'string' ? startCursor : null,
387
- hasNextPage: typeof hasNextPage === 'boolean' ? hasNextPage : null,
388
- hasPrevPage: typeof hasPrevPage === 'boolean' ? hasPrevPage : null
389
- },
390
- request: this._request,
391
- stream: enableStream === true
392
- });
393
333
  };
394
334
 
395
335
  _proto._normalizeField = function _normalizeField(parent, selection, record, data) {
@@ -400,20 +340,34 @@ function () {
400
340
 
401
341
  if (fieldValue == null) {
402
342
  if (fieldValue === undefined) {
403
- // Fields that are missing in the response are not set on the record.
404
- // There are three main cases where this can occur:
343
+ // Fields may be missing in the response in two main cases:
405
344
  // - Inside a client extension: the server will not generally return
406
345
  // values for these fields, but a local update may provide them.
407
- // - Fields on abstract types: these may be missing if the concrete
408
- // response type does not match the abstract type.
409
- //
410
- // Otherwise, missing fields usually indicate a server or user error (
411
- // the latter for manually constructed payloads).
412
- if (process.env.NODE_ENV !== "production") {
413
- process.env.NODE_ENV !== "production" ? warning(this._isClientExtension || parent.kind === LINKED_FIELD && parent.concreteType == null ? true : Object.prototype.hasOwnProperty.call(data, responseKey), 'RelayResponseNormalizer: Payload did not contain a value ' + 'for field `%s: %s`. Check that you are parsing with the same ' + 'query that was used to fetch the payload.', responseKey, storageKey) : void 0;
346
+ // - Inside an abstract type refinement where the concrete type does
347
+ // not conform to the interface/union.
348
+ // However an otherwise-required field may also be missing if the server
349
+ // is configured to skip fields with `null` values, in which case the
350
+ // client is assumed to be correctly configured with
351
+ // treatMissingFieldsAsNull=true.
352
+ var isOptionalField = this._isClientExtension || this._isUnmatchedAbstractType;
353
+
354
+ if (isOptionalField) {
355
+ // Field not expected to exist regardless of whether the server is pruning null
356
+ // fields or not.
357
+ return;
358
+ } else if (!this._treatMissingFieldsAsNull) {
359
+ // Not optional and the server is not pruning null fields: field is expected
360
+ // to be present
361
+ if (process.env.NODE_ENV !== "production") {
362
+ process.env.NODE_ENV !== "production" ? warning(false, 'RelayResponseNormalizer: Payload did not contain a value ' + 'for field `%s: %s`. Check that you are parsing with the same ' + 'query that was used to fetch the payload.', responseKey, storageKey) : void 0;
363
+ }
364
+
365
+ return;
414
366
  }
367
+ }
415
368
 
416
- return;
369
+ if (selection.kind === SCALAR_FIELD && process.env.NODE_ENV !== "production") {
370
+ this._validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue);
417
371
  }
418
372
 
419
373
  RelayModernRecord.setValue(record, storageKey, null);
@@ -421,6 +375,8 @@ function () {
421
375
  }
422
376
 
423
377
  if (selection.kind === SCALAR_FIELD) {
378
+ this._validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue);
379
+
424
380
  RelayModernRecord.setValue(record, storageKey, fieldValue);
425
381
  } else if (selection.kind === LINKED_FIELD) {
426
382
  this._path.push(responseKey);
@@ -442,36 +398,30 @@ function () {
442
398
  var _field$concreteType;
443
399
 
444
400
  !(typeof fieldValue === 'object' && fieldValue) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected data for field `%s` to be an object.', storageKey) : invariant(false) : void 0;
445
- var nextID = this._getDataId(
446
- /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
447
- * suppresses an error found when Flow v0.98 was deployed. To see the
448
- * error delete this comment and run Flow. */
449
- fieldValue,
450
- /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
451
- * suppresses an error found when Flow v0.98 was deployed. To see the
452
- * error delete this comment and run Flow. */
401
+ var nextID = this._getDataId( // $FlowFixMe[incompatible-variance]
402
+ fieldValue, // $FlowFixMe[incompatible-variance]
453
403
  (_field$concreteType = field.concreteType) !== null && _field$concreteType !== void 0 ? _field$concreteType : this._getRecordType(fieldValue)) || // Reuse previously generated client IDs
454
404
  RelayModernRecord.getLinkedRecordID(record, storageKey) || generateClientID(RelayModernRecord.getDataID(record), storageKey);
455
405
  !(typeof nextID === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected id on field `%s` to be a string.', storageKey) : invariant(false) : void 0;
406
+
407
+ if (process.env.NODE_ENV !== "production") {
408
+ this._validateConflictingLinkedFieldsWithIdenticalId(record, RelayModernRecord.getLinkedRecordID(record, storageKey), nextID, storageKey);
409
+ }
410
+
456
411
  RelayModernRecord.setLinkedRecordID(record, storageKey, nextID);
457
412
 
458
413
  var nextRecord = this._recordSource.get(nextID);
459
414
 
460
415
  if (!nextRecord) {
461
- /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
462
- * suppresses an error found when Flow v0.98 was deployed. To see the
463
- * error delete this comment and run Flow. */
464
- var _typeName2 = field.concreteType || this._getRecordType(fieldValue);
416
+ // $FlowFixMe[incompatible-variance]
417
+ var _typeName4 = field.concreteType || this._getRecordType(fieldValue);
465
418
 
466
- nextRecord = RelayModernRecord.create(nextID, _typeName2);
419
+ nextRecord = RelayModernRecord.create(nextID, _typeName4);
467
420
 
468
421
  this._recordSource.set(nextID, nextRecord);
469
422
  } else if (process.env.NODE_ENV !== "production") {
470
423
  this._validateRecordType(nextRecord, field, fieldValue);
471
- }
472
- /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
473
- * suppresses an error found when Flow v0.98 was deployed. To see the error
474
- * delete this comment and run Flow. */
424
+ } // $FlowFixMe[incompatible-variance]
475
425
 
476
426
 
477
427
  this._traverseSelections(field, nextRecord, fieldValue);
@@ -495,14 +445,8 @@ function () {
495
445
  _this._path.push(String(nextIndex));
496
446
 
497
447
  !(typeof item === 'object') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected elements for field `%s` to be ' + 'objects.', storageKey) : invariant(false) : void 0;
498
- var nextID = _this._getDataId(
499
- /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
500
- * suppresses an error found when Flow v0.98 was deployed. To see the
501
- * error delete this comment and run Flow. */
502
- item,
503
- /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
504
- * suppresses an error found when Flow v0.98 was deployed. To see the
505
- * error delete this comment and run Flow. */
448
+ var nextID = _this._getDataId( // $FlowFixMe[incompatible-variance]
449
+ item, // $FlowFixMe[incompatible-variance]
506
450
  (_field$concreteType2 = field.concreteType) !== null && _field$concreteType2 !== void 0 ? _field$concreteType2 : _this._getRecordType(item)) || prevIDs && prevIDs[nextIndex] || // Reuse previously generated client IDs:
507
451
  generateClientID(RelayModernRecord.getDataID(record), storageKey, nextIndex);
508
452
  !(typeof nextID === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayResponseNormalizer: Expected id of elements of field `%s` to ' + 'be strings.', storageKey) : invariant(false) : void 0;
@@ -511,20 +455,19 @@ function () {
511
455
  var nextRecord = _this._recordSource.get(nextID);
512
456
 
513
457
  if (!nextRecord) {
514
- /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
515
- * suppresses an error found when Flow v0.98 was deployed. To see the
516
- * error delete this comment and run Flow. */
517
- var _typeName3 = field.concreteType || _this._getRecordType(item);
458
+ // $FlowFixMe[incompatible-variance]
459
+ var _typeName5 = field.concreteType || _this._getRecordType(item);
518
460
 
519
- nextRecord = RelayModernRecord.create(nextID, _typeName3);
461
+ nextRecord = RelayModernRecord.create(nextID, _typeName5);
520
462
 
521
463
  _this._recordSource.set(nextID, nextRecord);
522
464
  } else if (process.env.NODE_ENV !== "production") {
523
465
  _this._validateRecordType(nextRecord, field, item);
524
466
  }
525
- /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
526
- * suppresses an error found when Flow v0.98 was deployed. To see the
527
- * error delete this comment and run Flow. */
467
+
468
+ if (prevIDs && process.env.NODE_ENV !== "production") {
469
+ _this._validateConflictingLinkedFieldsWithIdenticalId(record, prevIDs[nextIndex], nextID, storageKey);
470
+ } // $FlowFixMe[incompatible-variance]
528
471
 
529
472
 
530
473
  _this._traverseSelections(field, nextRecord, item);
@@ -542,14 +485,36 @@ function () {
542
485
  var _field$concreteType3;
543
486
 
544
487
  var typeName = (_field$concreteType3 = field.concreteType) !== null && _field$concreteType3 !== void 0 ? _field$concreteType3 : this._getRecordType(payload);
545
- process.env.NODE_ENV !== "production" ? warning(isClientID(RelayModernRecord.getDataID(record)) || RelayModernRecord.getType(record) === typeName, 'RelayResponseNormalizer: Invalid record `%s`. Expected %s to be ' + 'consistent, but the record was assigned conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', RelayModernRecord.getDataID(record), TYPENAME_KEY, RelayModernRecord.getType(record), typeName) : void 0;
488
+ var dataID = RelayModernRecord.getDataID(record);
489
+ process.env.NODE_ENV !== "production" ? warning(isClientID(dataID) && dataID !== ROOT_ID || RelayModernRecord.getType(record) === typeName, 'RelayResponseNormalizer: Invalid record `%s`. Expected %s to be ' + 'consistent, but the record was assigned conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', dataID, TYPENAME_KEY, RelayModernRecord.getType(record), typeName) : void 0;
490
+ }
491
+ /**
492
+ * Warns if a single response contains conflicting fields with the same id
493
+ */
494
+ ;
495
+
496
+ _proto._validateConflictingFieldsWithIdenticalId = function _validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue) {
497
+ if (process.env.NODE_ENV !== "production") {
498
+ var dataID = RelayModernRecord.getDataID(record);
499
+ var previousValue = RelayModernRecord.getValue(record, storageKey);
500
+ process.env.NODE_ENV !== "production" ? warning(storageKey === TYPENAME_KEY || previousValue === undefined || previousValue === fieldValue, 'RelayResponseNormalizer: Invalid record. The record contains two ' + 'instances of the same id: `%s` with conflicting field, %s and its values: %s and %s. ' + 'If two fields are different but share ' + 'the same id, one field will overwrite the other.', dataID, storageKey, previousValue, fieldValue) : void 0;
501
+ }
502
+ }
503
+ /**
504
+ * Warns if a single response contains conflicting fields with the same id
505
+ */
506
+ ;
507
+
508
+ _proto._validateConflictingLinkedFieldsWithIdenticalId = function _validateConflictingLinkedFieldsWithIdenticalId(record, prevID, nextID, storageKey) {
509
+ if (process.env.NODE_ENV !== "production") {
510
+ process.env.NODE_ENV !== "production" ? warning(prevID === undefined || prevID === nextID, 'RelayResponseNormalizer: Invalid record. The record contains ' + 'references to the conflicting field, %s and its id values: %s and %s. ' + 'We need to make sure that the record the field points ' + 'to remains consistent or one field will overwrite the other.', storageKey, prevID, nextID) : void 0;
511
+ }
546
512
  };
547
513
 
548
514
  return RelayResponseNormalizer;
549
- }(); // eslint-disable-next-line no-func-assign
550
-
515
+ }();
551
516
 
552
- normalize = RelayProfiler.instrument('RelayResponseNormalizer.normalize', normalize);
517
+ var instrumentedNormalize = RelayProfiler.instrument('RelayResponseNormalizer.normalize', normalize);
553
518
  module.exports = {
554
- normalize: normalize
519
+ normalize: instrumentedNormalize
555
520
  };
@@ -204,6 +204,7 @@ var RelayStoreUtils = {
204
204
  ROOT_TYPE: '__Root',
205
205
  TYPENAME_KEY: '__typename',
206
206
  INVALIDATED_AT_KEY: '__invalidated_at',
207
+ IS_WITHIN_UNMATCHED_TYPE_REFINEMENT: '__isWithinUnmatchedTypeRefinement',
207
208
  formatStorageKey: formatStorageKey,
208
209
  getArgumentValue: getArgumentValue,
209
210
  getArgumentValues: getArgumentValues,
@@ -13,10 +13,14 @@
13
13
 
14
14
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
15
15
 
16
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
16
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
17
17
 
18
18
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
19
19
 
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
+
20
24
  var inspect = function inspect() {};
21
25
 
22
26
  if (process.env.NODE_ENV !== "production") {
@@ -134,7 +138,7 @@ if (process.env.NODE_ENV !== "production") {
134
138
  return record;
135
139
  }
136
140
 
137
- return new Proxy((0, _objectSpread2["default"])({}, record), {
141
+ return new Proxy(_objectSpread({}, record), {
138
142
  get: function get(target, prop) {
139
143
  var value = target[prop];
140
144
 
@@ -148,9 +152,7 @@ if (process.env.NODE_ENV !== "production") {
148
152
  }
149
153
 
150
154
  if (Array.isArray(value.__refs)) {
151
- /* $FlowFixMe(>=0.111.0) This comment suppresses an error found
152
- * when Flow v0.111.0 was deployed. To see the error, delete this
153
- * comment and run Flow. */
155
+ // $FlowFixMe[incompatible-call]
154
156
  return value.__refs.map(function (ref) {
155
157
  return getWrappedRecord(source, ref);
156
158
  });
@@ -163,10 +165,8 @@ if (process.env.NODE_ENV !== "production") {
163
165
  };
164
166
 
165
167
  inspect = function inspect(environment, dataID) {
166
- var _dataID;
167
-
168
168
  installDevtoolFormatters();
169
- return getWrappedRecord(environment.getStore().getSource(), (_dataID = dataID) !== null && _dataID !== void 0 ? _dataID : 'client:root');
169
+ return getWrappedRecord(environment.getStore().getSource(), dataID !== null && dataID !== void 0 ? dataID : 'client:root');
170
170
  };
171
171
  }
172
172
 
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+ // flowlint ambiguous-object-type:error
11
+ 'use strict';
12
+
13
+ var PREFIX = 'client:__type:';
14
+ var TYPE_SCHEMA_TYPE = '__TypeSchema';
15
+
16
+ function generateTypeID(typeName) {
17
+ return PREFIX + typeName;
18
+ }
19
+
20
+ function isTypeID(id) {
21
+ return id.indexOf(PREFIX) === 0;
22
+ }
23
+
24
+ module.exports = {
25
+ generateTypeID: generateTypeID,
26
+ isTypeID: isTypeID,
27
+ TYPE_SCHEMA_TYPE: TYPE_SCHEMA_TYPE
28
+ };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+ // flowlint ambiguous-object-type:error
11
+ 'use strict';
12
+
13
+ var areEqual = require("fbjs/lib/areEqual");
14
+
15
+ var invariant = require("fbjs/lib/invariant");
16
+
17
+ var _require = require('../util/RelayConcreteNode'),
18
+ SCALAR_FIELD = _require.SCALAR_FIELD;
19
+
20
+ var _require2 = require('./RelayStoreUtils'),
21
+ getHandleStorageKey = _require2.getHandleStorageKey;
22
+
23
+ /**
24
+ * @private
25
+ *
26
+ * Creates a clone of the supplied `handleField` by finding the original scalar
27
+ * field (on which the handle was declared) among the sibling `selections`.
28
+ */
29
+ function cloneRelayScalarHandleSourceField(handleField, selections, variables) {
30
+ var sourceField = selections.find(function (source) {
31
+ return source.kind === SCALAR_FIELD && source.name === handleField.name && source.alias === handleField.alias && areEqual(source.args, handleField.args);
32
+ });
33
+ !(sourceField && sourceField.kind === SCALAR_FIELD) ? process.env.NODE_ENV !== "production" ? invariant(false, 'cloneRelayScalarHandleSourceField: Expected a corresponding source field for ' + 'handle `%s`.', handleField.handle) : invariant(false) : void 0;
34
+ var handleKey = getHandleStorageKey(handleField, variables);
35
+ return {
36
+ kind: 'ScalarField',
37
+ alias: sourceField.alias,
38
+ name: handleKey,
39
+ storageKey: handleKey,
40
+ args: null
41
+ };
42
+ }
43
+
44
+ module.exports = cloneRelayScalarHandleSourceField;