relay-runtime 18.2.0 → 19.0.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 (81) hide show
  1. package/experimental.js +1 -1
  2. package/experimental.js.flow +8 -6
  3. package/index.js +1 -1
  4. package/index.js.flow +3 -0
  5. package/lib/experimental.js +5 -2
  6. package/lib/index.js +3 -0
  7. package/lib/multi-actor-environment/ActorSpecificEnvironment.js +1 -1
  8. package/lib/mutations/RelayRecordSourceProxy.js +2 -1
  9. package/lib/mutations/createUpdatableProxy.js +1 -1
  10. package/lib/mutations/validateMutation.js +2 -2
  11. package/lib/network/RelayObservable.js +1 -3
  12. package/lib/network/wrapNetworkWithLogObserver.js +2 -2
  13. package/lib/query/fetchQuery.js +1 -1
  14. package/lib/store/DataChecker.js +4 -5
  15. package/lib/store/OperationExecutor.js +11 -0
  16. package/lib/store/RelayModernEnvironment.js +13 -4
  17. package/lib/store/RelayModernFragmentSpecResolver.js +4 -4
  18. package/lib/store/RelayModernStore.js +43 -21
  19. package/lib/store/RelayPublishQueue.js +11 -15
  20. package/lib/store/RelayReader.js +131 -151
  21. package/lib/store/RelayReferenceMarker.js +3 -4
  22. package/lib/store/RelayResponseNormalizer.js +47 -26
  23. package/lib/store/RelayStoreSubscriptions.js +2 -2
  24. package/lib/store/RelayStoreUtils.js +8 -0
  25. package/lib/store/ResolverFragments.js +2 -2
  26. package/lib/store/createRelayLoggingContext.js +17 -0
  27. package/lib/store/generateTypenamePrefixedDataID.js +9 -0
  28. package/lib/store/live-resolvers/LiveResolverCache.js +2 -1
  29. package/lib/store/live-resolvers/resolverDataInjector.js +4 -4
  30. package/lib/store/observeFragmentExperimental.js +60 -13
  31. package/lib/store/observeQueryExperimental.js +21 -0
  32. package/lib/util/RelayFeatureFlags.js +6 -1
  33. package/lib/util/handlePotentialSnapshotErrors.js +11 -8
  34. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +1 -0
  35. package/mutations/RelayRecordSourceProxy.js.flow +4 -0
  36. package/mutations/createUpdatableProxy.js.flow +1 -1
  37. package/mutations/validateMutation.js.flow +3 -3
  38. package/network/RelayNetworkTypes.js.flow +3 -0
  39. package/network/RelayObservable.js.flow +1 -5
  40. package/network/wrapNetworkWithLogObserver.js.flow +19 -1
  41. package/package.json +1 -1
  42. package/query/fetchQuery.js.flow +1 -1
  43. package/store/DataChecker.js.flow +5 -2
  44. package/store/OperationExecutor.js.flow +12 -1
  45. package/store/RelayExperimentalGraphResponseTransform.js.flow +4 -4
  46. package/store/RelayModernEnvironment.js.flow +22 -6
  47. package/store/RelayModernFragmentSpecResolver.js.flow +6 -6
  48. package/store/RelayModernSelector.js.flow +2 -0
  49. package/store/RelayModernStore.js.flow +74 -27
  50. package/store/RelayPublishQueue.js.flow +32 -21
  51. package/store/RelayReader.js.flow +159 -96
  52. package/store/RelayReferenceMarker.js.flow +3 -4
  53. package/store/RelayResponseNormalizer.js.flow +93 -67
  54. package/store/RelayStoreSubscriptions.js.flow +2 -2
  55. package/store/RelayStoreTypes.js.flow +33 -4
  56. package/store/RelayStoreUtils.js.flow +29 -0
  57. package/store/ResolverCache.js.flow +2 -2
  58. package/store/ResolverFragments.js.flow +5 -3
  59. package/store/StoreInspector.js.flow +5 -0
  60. package/store/createRelayContext.js.flow +3 -2
  61. package/store/createRelayLoggingContext.js.flow +46 -0
  62. package/store/generateTypenamePrefixedDataID.js.flow +25 -0
  63. package/store/live-resolvers/LiveResolverCache.js.flow +2 -1
  64. package/store/live-resolvers/resolverDataInjector.js.flow +10 -6
  65. package/store/observeFragmentExperimental.js.flow +82 -28
  66. package/store/observeQueryExperimental.js.flow +61 -0
  67. package/store/waitForFragmentExperimental.js.flow +4 -3
  68. package/util/NormalizationNode.js.flow +2 -1
  69. package/util/RelayConcreteNode.js.flow +2 -0
  70. package/util/RelayError.js.flow +1 -0
  71. package/util/RelayFeatureFlags.js.flow +18 -0
  72. package/util/RelayRuntimeTypes.js.flow +6 -3
  73. package/util/getPaginationVariables.js.flow +2 -0
  74. package/util/handlePotentialSnapshotErrors.js.flow +23 -11
  75. package/util/registerEnvironmentWithDevTools.js.flow +4 -2
  76. package/util/withProvidedVariables.js.flow +1 -0
  77. package/util/withStartAndDuration.js.flow +3 -0
  78. package/relay-runtime-experimental.js +0 -4
  79. package/relay-runtime-experimental.min.js +0 -9
  80. package/relay-runtime.js +0 -4
  81. package/relay-runtime.min.js +0 -9
@@ -54,6 +54,7 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
54
54
  this._recordSource = recordSource;
55
55
  this._variables = variables;
56
56
  this._shouldProcessClientComponents = options.shouldProcessClientComponents;
57
+ this._log = options.log;
57
58
  }
58
59
  var _proto = RelayResponseNormalizer.prototype;
59
60
  _proto.normalizeResponse = function normalizeResponse(node, dataID, data, errors) {
@@ -205,8 +206,6 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
205
206
  this._normalizeActorChange(selection, record, data);
206
207
  break;
207
208
  case 'RelayResolver':
208
- this._normalizeResolver(selection, record, data);
209
- break;
210
209
  case 'RelayLiveResolver':
211
210
  this._normalizeResolver(selection, record, data);
212
211
  break;
@@ -289,7 +288,8 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
289
288
  var responseKey = selection.alias || selection.name;
290
289
  var storageKey = getStorageKey(selection, this._variables);
291
290
  var fieldValue = data[responseKey];
292
- if (fieldValue == null || RelayFeatureFlags.ENABLE_NONCOMPLIANT_ERROR_HANDLING_ON_LISTS && Array.isArray(fieldValue) && fieldValue.length === 0) {
291
+ var isNoncompliantlyNullish = RelayFeatureFlags.ENABLE_NONCOMPLIANT_ERROR_HANDLING_ON_LISTS && Array.isArray(fieldValue) && fieldValue.length === 0;
292
+ if (fieldValue == null || isNoncompliantlyNullish) {
293
293
  if (fieldValue === undefined) {
294
294
  var isOptionalField = this._isClientExtension || this._isUnmatchedAbstractType;
295
295
  if (isOptionalField) {
@@ -301,12 +301,18 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
301
301
  return;
302
302
  }
303
303
  }
304
- if (process.env.NODE_ENV !== "production") {
305
- if (selection.kind === 'ScalarField') {
306
- this._validateConflictingFieldsWithIdenticalId(record, storageKey, null);
304
+ if (selection.kind === 'ScalarField') {
305
+ this._validateConflictingFieldsWithIdenticalId(record, storageKey, null);
306
+ }
307
+ if (isNoncompliantlyNullish) {
308
+ if (selection.kind === 'LinkedField') {
309
+ RelayModernRecord.setLinkedRecordIDs(record, storageKey, []);
310
+ } else {
311
+ RelayModernRecord.setValue(record, storageKey, []);
307
312
  }
313
+ } else {
314
+ RelayModernRecord.setValue(record, storageKey, null);
308
315
  }
309
- RelayModernRecord.setValue(record, storageKey, null);
310
316
  var errorTrie = this._errorTrie;
311
317
  if (errorTrie != null) {
312
318
  var errors = getErrorsByKey(errorTrie, responseKey);
@@ -317,9 +323,7 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
317
323
  return;
318
324
  }
319
325
  if (selection.kind === 'ScalarField') {
320
- if (process.env.NODE_ENV !== "production") {
321
- this._validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue);
322
- }
326
+ this._validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue);
323
327
  RelayModernRecord.setValue(record, storageKey, fieldValue);
324
328
  } else if (selection.kind === 'LinkedField') {
325
329
  this._path.push(responseKey);
@@ -387,16 +391,14 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
387
391
  !(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;
388
392
  var nextID = this._getDataId(fieldValue, (_field$concreteType2 = field.concreteType) !== null && _field$concreteType2 !== void 0 ? _field$concreteType2 : this._getRecordType(fieldValue)) || RelayModernRecord.getLinkedRecordID(record, storageKey) || generateClientID(RelayModernRecord.getDataID(record), storageKey);
389
393
  !(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;
390
- if (process.env.NODE_ENV !== "production") {
391
- this._validateConflictingLinkedFieldsWithIdenticalId(RelayModernRecord.getLinkedRecordID(record, storageKey), nextID, storageKey);
392
- }
394
+ this._validateConflictingLinkedFieldsWithIdenticalId(RelayModernRecord.getLinkedRecordID(record, storageKey), nextID, storageKey);
393
395
  RelayModernRecord.setLinkedRecordID(record, storageKey, nextID);
394
396
  var nextRecord = this._recordSource.get(nextID);
395
397
  if (!nextRecord) {
396
398
  var typeName = field.concreteType || this._getRecordType(fieldValue);
397
399
  nextRecord = RelayModernRecord.create(nextID, typeName);
398
400
  this._recordSource.set(nextID, nextRecord);
399
- } else if (process.env.NODE_ENV !== "production") {
401
+ } else {
400
402
  this._validateRecordType(nextRecord, field, fieldValue);
401
403
  }
402
404
  this._traverseSelections(field, nextRecord, fieldValue);
@@ -424,13 +426,11 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
424
426
  var typeName = field.concreteType || _this._getRecordType(item);
425
427
  nextRecord = RelayModernRecord.create(nextID, typeName);
426
428
  _this._recordSource.set(nextID, nextRecord);
427
- } else if (process.env.NODE_ENV !== "production") {
429
+ } else {
428
430
  _this._validateRecordType(nextRecord, field, item);
429
431
  }
430
- if (process.env.NODE_ENV !== "production") {
431
- if (prevIDs) {
432
- _this._validateConflictingLinkedFieldsWithIdenticalId(prevIDs[nextIndex], nextID, storageKey);
433
- }
432
+ if (prevIDs) {
433
+ _this._validateConflictingLinkedFieldsWithIdenticalId(prevIDs[nextIndex], nextID, storageKey);
434
434
  }
435
435
  _this._traverseSelections(field, nextRecord, item);
436
436
  _this._errorTrie = oldErrorTrie;
@@ -439,21 +439,42 @@ var RelayResponseNormalizer = /*#__PURE__*/function () {
439
439
  RelayModernRecord.setLinkedRecordIDs(record, storageKey, nextIDs);
440
440
  };
441
441
  _proto._validateRecordType = function _validateRecordType(record, field, payload) {
442
- var _field$concreteType4;
443
- var typeName = (_field$concreteType4 = field.concreteType) !== null && _field$concreteType4 !== void 0 ? _field$concreteType4 : this._getRecordType(payload);
444
- var dataID = RelayModernRecord.getDataID(record);
445
- 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;
442
+ if (RelayFeatureFlags.ENABLE_STORE_ID_COLLISION_LOGGING) {
443
+ var _field$concreteType4;
444
+ var typeName = (_field$concreteType4 = field.concreteType) !== null && _field$concreteType4 !== void 0 ? _field$concreteType4 : this._getRecordType(payload);
445
+ var dataID = RelayModernRecord.getDataID(record);
446
+ var expected = isClientID(dataID) && dataID !== ROOT_ID || RelayModernRecord.getType(record) === typeName;
447
+ if (!expected) {
448
+ var logEvent = {
449
+ name: 'idCollision.typename',
450
+ previous_typename: RelayModernRecord.getType(record),
451
+ new_typename: typeName
452
+ };
453
+ if (this._log != null) {
454
+ this._log(logEvent);
455
+ }
456
+ }
457
+ }
458
+ if (process.env.NODE_ENV !== "production") {
459
+ var _field$concreteType5;
460
+ var _typeName3 = (_field$concreteType5 = field.concreteType) !== null && _field$concreteType5 !== void 0 ? _field$concreteType5 : this._getRecordType(payload);
461
+ var _dataID = RelayModernRecord.getDataID(record);
462
+ var _expected = isClientID(_dataID) && _dataID !== ROOT_ID || RelayModernRecord.getType(record) === _typeName3;
463
+ process.env.NODE_ENV !== "production" ? warning(_expected, '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), _typeName3) : void 0;
464
+ }
446
465
  };
447
466
  _proto._validateConflictingFieldsWithIdenticalId = function _validateConflictingFieldsWithIdenticalId(record, storageKey, fieldValue) {
448
467
  if (process.env.NODE_ENV !== "production") {
449
- var dataID = RelayModernRecord.getDataID(record);
450
468
  var previousValue = RelayModernRecord.getValue(record, storageKey);
451
- process.env.NODE_ENV !== "production" ? warning(storageKey === TYPENAME_KEY || previousValue === undefined || areEqual(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;
469
+ var dataID = RelayModernRecord.getDataID(record);
470
+ var expected = storageKey === TYPENAME_KEY || previousValue === undefined || areEqual(previousValue, fieldValue);
471
+ process.env.NODE_ENV !== "production" ? warning(expected, '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;
452
472
  }
453
473
  };
454
474
  _proto._validateConflictingLinkedFieldsWithIdenticalId = function _validateConflictingLinkedFieldsWithIdenticalId(prevID, nextID, storageKey) {
455
475
  if (process.env.NODE_ENV !== "production") {
456
- 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;
476
+ var expected = prevID === undefined || prevID === nextID;
477
+ process.env.NODE_ENV !== "production" ? warning(expected, '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;
457
478
  }
458
479
  };
459
480
  return RelayResponseNormalizer;
@@ -59,7 +59,7 @@ var RelayStoreSubscriptions = /*#__PURE__*/function () {
59
59
  missingLiveResolverFields: backup.missingLiveResolverFields,
60
60
  seenRecords: backup.seenRecords,
61
61
  selector: backup.selector,
62
- errorResponseFields: backup.errorResponseFields
62
+ fieldErrors: backup.fieldErrors
63
63
  };
64
64
  } else {
65
65
  subscription.stale = true;
@@ -94,7 +94,7 @@ var RelayStoreSubscriptions = /*#__PURE__*/function () {
94
94
  missingLiveResolverFields: nextSnapshot.missingLiveResolverFields,
95
95
  seenRecords: nextSnapshot.seenRecords,
96
96
  selector: nextSnapshot.selector,
97
- errorResponseFields: nextSnapshot.errorResponseFields
97
+ fieldErrors: nextSnapshot.fieldErrors
98
98
  };
99
99
  if (process.env.NODE_ENV !== "production") {
100
100
  deepFreeze(nextSnapshot);
@@ -4,6 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
5
5
  var getRelayHandleKey = require('../util/getRelayHandleKey');
6
6
  var RelayConcreteNode = require('../util/RelayConcreteNode');
7
+ var RelayFeatureFlags = require('../util/RelayFeatureFlags');
7
8
  var _require = require('../util/stableCopy'),
8
9
  stableCopy = _require.stableCopy;
9
10
  var invariant = require('invariant');
@@ -14,6 +15,7 @@ var VARIABLE = RelayConcreteNode.VARIABLE,
14
15
  var ERRORS_KEY = '__errors';
15
16
  var MODULE_COMPONENT_KEY_PREFIX = '__module_component_';
16
17
  var MODULE_OPERATION_KEY_PREFIX = '__module_operation_';
18
+ var RELAY_READ_TIME_RESOLVER_KEY_PREFIX = '$r:';
17
19
  function getArgumentValue(arg, variables) {
18
20
  if (arg.kind === VARIABLE) {
19
21
  return getStableVariableValue(arg.variableName, variables);
@@ -76,6 +78,10 @@ function getStorageKey(field, variables) {
76
78
  var name = field.name;
77
79
  return args && args.length !== 0 ? formatStorageKey(name, getArgumentValues(args, variables)) : name;
78
80
  }
81
+ function getReadTimeResolverStorageKey(field, variables) {
82
+ var storageKey = getStorageKey(field, variables);
83
+ return RelayFeatureFlags.ENABLE_READ_TIME_RESOLVER_STORAGE_KEY_PREFIX ? '$r:' + storageKey : storageKey;
84
+ }
79
85
  function getArguments(field) {
80
86
  if (field.kind === 'RelayResolver' || field.kind === 'RelayLiveResolver') {
81
87
  var _field$fragment2;
@@ -141,11 +147,13 @@ var RelayStoreUtils = {
141
147
  RELAY_RESOLVER_SNAPSHOT_KEY: '__resolverSnapshot',
142
148
  RELAY_RESOLVER_ERROR_KEY: '__resolverError',
143
149
  RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS: '__resolverOutputTypeRecordIDs',
150
+ RELAY_READ_TIME_RESOLVER_KEY_PREFIX: RELAY_READ_TIME_RESOLVER_KEY_PREFIX,
144
151
  formatStorageKey: formatStorageKey,
145
152
  getArgumentValue: getArgumentValue,
146
153
  getArgumentValues: getArgumentValues,
147
154
  getHandleStorageKey: getHandleStorageKey,
148
155
  getStorageKey: getStorageKey,
156
+ getReadTimeResolverStorageKey: getReadTimeResolverStorageKey,
149
157
  getStableStorageKey: getStableStorageKey,
150
158
  getModuleComponentKey: getModuleComponentKey,
151
159
  getModuleOperationKey: getModuleOperationKey
@@ -28,8 +28,8 @@ function readFragment(fragmentInput, fragmentKey) {
28
28
  var _context$getDataForRe = context.getDataForResolverFragment(fragmentSelector, fragmentKey),
29
29
  data = _context$getDataForRe.data,
30
30
  isMissingData = _context$getDataForRe.isMissingData,
31
- errorResponseFields = _context$getDataForRe.errorResponseFields;
32
- if (isMissingData || errorResponseFields != null && errorResponseFields.some(eventShouldThrow)) {
31
+ fieldErrors = _context$getDataForRe.fieldErrors;
32
+ if (isMissingData || fieldErrors != null && fieldErrors.some(eventShouldThrow)) {
33
33
  throw RESOLVER_FRAGMENT_ERRORED_SENTINEL;
34
34
  }
35
35
  return data;
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ var invariant = require('invariant');
4
+ var relayLoggingContext;
5
+ var firstReact;
6
+ function createRelayLoggingContext(react) {
7
+ if (!relayLoggingContext) {
8
+ relayLoggingContext = react.createContext(null);
9
+ if (process.env.NODE_ENV !== "production") {
10
+ relayLoggingContext.displayName = 'RelayLoggingContext';
11
+ }
12
+ firstReact = react;
13
+ }
14
+ !(react === firstReact) ? process.env.NODE_ENV !== "production" ? invariant(false, '[createRelayLoggingContext]: You are passing a different instance of React', react.version) : invariant(false) : void 0;
15
+ return relayLoggingContext;
16
+ }
17
+ module.exports = createRelayLoggingContext;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var TYPENAME_PREFIX = '__type:';
4
+ function generateTypenamePrefixedDataID(typeName, dataID) {
5
+ return "".concat(TYPENAME_PREFIX).concat(typeName, ":").concat(dataID);
6
+ }
7
+ module.exports = {
8
+ generateTypenamePrefixedDataID: generateTypenamePrefixedDataID
9
+ };
@@ -22,6 +22,7 @@ var _require5 = require('../RelayStoreUtils'),
22
22
  RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS = _require5.RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS,
23
23
  RELAY_RESOLVER_SNAPSHOT_KEY = _require5.RELAY_RESOLVER_SNAPSHOT_KEY,
24
24
  RELAY_RESOLVER_VALUE_KEY = _require5.RELAY_RESOLVER_VALUE_KEY,
25
+ getReadTimeResolverStorageKey = _require5.getReadTimeResolverStorageKey,
25
26
  getStorageKey = _require5.getStorageKey;
26
27
  var getOutputTypeRecordIDs = require('./getOutputTypeRecordIDs');
27
28
  var isLiveStateValue = require('./isLiveStateValue');
@@ -55,7 +56,7 @@ var LiveResolverCache = /*#__PURE__*/function () {
55
56
  _proto.readFromCacheOrEvaluate = function readFromCacheOrEvaluate(recordID, field, variables, evaluate, getDataForResolverFragment) {
56
57
  var recordSource = this._getRecordSource();
57
58
  var record = expectRecord(recordSource, recordID);
58
- var storageKey = getStorageKey(field, variables);
59
+ var storageKey = getReadTimeResolverStorageKey(field, variables);
59
60
  var linkedID = RelayModernRecord.getLinkedRecordID(record, storageKey);
60
61
  var linkedRecord = linkedID == null ? null : recordSource.get(linkedID);
61
62
  var updatedDataIDs;
@@ -5,26 +5,26 @@ var _require = require('../ResolverFragments'),
5
5
  var invariant = require('invariant');
6
6
  function resolverDataInjector(fragment, _resolverFn, fieldName, isRequiredField) {
7
7
  var resolverFn = _resolverFn;
8
- return function (fragmentKey, args) {
8
+ return function (fragmentKey, args, resolverContext) {
9
9
  var data = readFragment(fragment, fragmentKey);
10
10
  if (fieldName != null) {
11
11
  if (data == null) {
12
12
  if (isRequiredField === true) {
13
13
  !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected required resolver field `%s` in fragment `%s` to be present. But resolvers fragment data is null/undefined.', fieldName, fragment.name) : invariant(false) : void 0;
14
14
  } else {
15
- return resolverFn(null, args);
15
+ return resolverFn(null, args, resolverContext);
16
16
  }
17
17
  }
18
18
  if (fieldName in data) {
19
19
  if (isRequiredField === true) {
20
20
  !(data[fieldName] != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected required resolver field `%s` in fragment `%s` to be non-null.', fieldName, fragment.name) : invariant(false) : void 0;
21
21
  }
22
- return resolverFn(data[fieldName], args);
22
+ return resolverFn(data[fieldName], args, resolverContext);
23
23
  } else {
24
24
  !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Missing field `%s` in fragment `%s` in resolver response.', fieldName, fragment.name) : invariant(false) : void 0;
25
25
  }
26
26
  } else {
27
- return resolverFn(data, args);
27
+ return resolverFn(null, args, resolverContext);
28
28
  }
29
29
  };
30
30
  }
@@ -1,14 +1,17 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
3
4
  var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator").default;
5
+ var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/createForOfIteratorHelper"));
4
6
  var Observable = require('../network/RelayObservable');
5
- var _require = require('../query/GraphQLTag'),
6
- getFragment = _require.getFragment;
7
- var getPendingOperationsForFragment = require('../util/getPendingOperationsForFragment');
8
- var _require2 = require('../util/handlePotentialSnapshotErrors'),
9
- handlePotentialSnapshotErrors = _require2.handlePotentialSnapshotErrors;
10
- var _require3 = require('./RelayModernSelector'),
11
- getSelector = _require3.getSelector;
7
+ var _require = require('../query/fetchQueryInternal'),
8
+ getObservableForActiveRequest = _require.getObservableForActiveRequest;
9
+ var _require2 = require('../query/GraphQLTag'),
10
+ getFragment = _require2.getFragment;
11
+ var _require3 = require('../util/handlePotentialSnapshotErrors'),
12
+ handlePotentialSnapshotErrors = _require3.handlePotentialSnapshotErrors;
13
+ var _require4 = require('./RelayModernSelector'),
14
+ getSelector = _require4.getSelector;
12
15
  var invariant = require('invariant');
13
16
  function waitForFragmentData(_x, _x2, _x3) {
14
17
  return _waitForFragmentData.apply(this, arguments);
@@ -47,15 +50,15 @@ function observeFragment(environment, fragment, fragmentRef) {
47
50
  !(fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected a selector, got null.') : invariant(false) : void 0;
48
51
  switch (fragmentSelector.kind) {
49
52
  case 'SingularReaderSelector':
50
- return observeSelector(environment, fragment, fragmentSelector);
53
+ return observeSingularSelector(environment, fragment, fragmentSelector);
51
54
  case 'PluralReaderSelector':
52
55
  {
53
- !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Plural fragments are not supported') : invariant(false) : void 0;
56
+ return observePluralSelector(environment, fragment, fragmentSelector);
54
57
  }
55
58
  }
56
59
  !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'Unsupported fragment selector kind') : invariant(false) : void 0;
57
60
  }
58
- function observeSelector(environment, fragmentNode, fragmentSelector) {
61
+ function observeSingularSelector(environment, fragmentNode, fragmentSelector) {
59
62
  var snapshot = environment.lookup(fragmentSelector);
60
63
  return Observable.create(function (sink) {
61
64
  sink.next(snapshotToFragmentState(environment, fragmentNode, fragmentSelector.owner, snapshot));
@@ -67,6 +70,28 @@ function observeSelector(environment, fragmentNode, fragmentSelector) {
67
70
  };
68
71
  });
69
72
  }
73
+ function observePluralSelector(environment, fragmentNode, fragmentSelector) {
74
+ var snapshots = fragmentSelector.selectors.map(function (selector) {
75
+ return environment.lookup(selector);
76
+ });
77
+ return Observable.create(function (sink) {
78
+ var states = snapshots.map(function (snapshot, index) {
79
+ return snapshotToFragmentState(environment, fragmentNode, fragmentSelector.selectors[index].owner, snapshot);
80
+ });
81
+ sink.next(mergeFragmentStates(states));
82
+ var subscriptions = snapshots.map(function (snapshot, index) {
83
+ return environment.subscribe(snapshot, function (latestSnapshot) {
84
+ states[index] = snapshotToFragmentState(environment, fragmentNode, fragmentSelector.selectors[index].owner, latestSnapshot);
85
+ sink.next(mergeFragmentStates(states));
86
+ });
87
+ });
88
+ return function () {
89
+ return subscriptions.forEach(function (subscription) {
90
+ return subscription.dispose();
91
+ });
92
+ };
93
+ });
94
+ }
70
95
  function snapshotToFragmentState(environment, fragmentNode, owner, snapshot) {
71
96
  var missingLiveResolverFields = snapshot.missingLiveResolverFields != null && snapshot.missingLiveResolverFields.length > 0;
72
97
  var missingClientEdges = snapshot.missingClientEdges != null && snapshot.missingClientEdges.length > 0;
@@ -76,15 +101,14 @@ function snapshotToFragmentState(environment, fragmentNode, owner, snapshot) {
76
101
  };
77
102
  }
78
103
  if (snapshot.isMissingData) {
79
- var pendingOperations = getPendingOperationsForFragment(environment, fragmentNode, owner);
80
- if (pendingOperations != null) {
104
+ if (getObservableForActiveRequest(environment, owner) != null || environment.getOperationTracker().getPendingOperationsAffectingOwner(owner) != null) {
81
105
  return {
82
106
  state: 'loading'
83
107
  };
84
108
  }
85
109
  }
86
110
  try {
87
- handlePotentialSnapshotErrors(environment, snapshot.errorResponseFields);
111
+ handlePotentialSnapshotErrors(environment, snapshot.fieldErrors);
88
112
  } catch (error) {
89
113
  return {
90
114
  error: error,
@@ -97,6 +121,29 @@ function snapshotToFragmentState(environment, fragmentNode, owner, snapshot) {
97
121
  value: snapshot.data
98
122
  };
99
123
  }
124
+ function mergeFragmentStates(states) {
125
+ var value = [];
126
+ var _iterator = (0, _createForOfIteratorHelper2["default"])(states),
127
+ _step;
128
+ try {
129
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
130
+ var state = _step.value;
131
+ if (state.state === 'ok') {
132
+ value.push(state.value);
133
+ } else {
134
+ return state;
135
+ }
136
+ }
137
+ } catch (err) {
138
+ _iterator.e(err);
139
+ } finally {
140
+ _iterator.f();
141
+ }
142
+ return {
143
+ state: 'ok',
144
+ value: value
145
+ };
146
+ }
100
147
  module.exports = {
101
148
  observeFragment: observeFragment,
102
149
  waitForFragmentData: waitForFragmentData
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
4
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
5
+ var _require = require('./observeFragmentExperimental'),
6
+ observeFragment = _require.observeFragment;
7
+ var _require2 = require('./RelayModernOperationDescriptor'),
8
+ createOperationDescriptor = _require2.createOperationDescriptor;
9
+ function observeQuery(environment, gqlQuery, variables) {
10
+ var operation = createOperationDescriptor(gqlQuery, variables);
11
+ var rootFragmentRef = {
12
+ __id: operation.fragment.dataID,
13
+ __fragments: (0, _defineProperty2["default"])({}, operation.fragment.node.name, operation.request.variables),
14
+ __fragmentOwner: operation.request
15
+ };
16
+ var fragmentNode = operation.request.node.fragment;
17
+ return observeFragment(environment, fragmentNode, rootFragmentRef);
18
+ }
19
+ module.exports = {
20
+ observeQuery: observeQuery
21
+ };
@@ -12,6 +12,7 @@ var RelayFeatureFlags = {
12
12
  MAX_DATA_ID_LENGTH: null,
13
13
  STRING_INTERN_LEVEL: 0,
14
14
  LOG_MISSING_RECORDS_IN_PROD: false,
15
+ ENABLE_STORE_ID_COLLISION_LOGGING: false,
15
16
  ENABLE_NONCOMPLIANT_ERROR_HANDLING_ON_LISTS: false,
16
17
  ENABLE_LOOSE_SUBSCRIPTION_ATTRIBUTION: false,
17
18
  ENABLE_OPERATION_TRACKER_OPTIMISTIC_UPDATES: false,
@@ -20,6 +21,10 @@ var RelayFeatureFlags = {
20
21
  MARK_RESOLVER_VALUES_AS_CLEAN_AFTER_FRAGMENT_REREAD: false,
21
22
  ENABLE_CYLE_DETECTION_IN_VARIABLES: false,
22
23
  ENABLE_ACTIVITY_COMPATIBILITY: false,
23
- ENABLE_READ_TIME_RESOLVER_STORAGE_KEY_PREFIX: true
24
+ ENABLE_READ_TIME_RESOLVER_STORAGE_KEY_PREFIX: true,
25
+ ENABLE_USE_PAGINATION_IS_LOADING_FIX: false,
26
+ DISALLOW_NESTED_UPDATES: false,
27
+ ENABLE_TYPENAME_PREFIXED_DATA_ID: false,
28
+ ENABLE_UI_CONTEXT_ON_RELAY_LOGGER: false
24
29
  };
25
30
  module.exports = RelayFeatureFlags;
@@ -1,22 +1,25 @@
1
1
  'use strict';
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
4
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
4
5
  var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/createForOfIteratorHelper"));
5
6
  var invariant = require('invariant');
6
- function handleFieldErrors(environment, errorResponseFields) {
7
- var _iterator = (0, _createForOfIteratorHelper2["default"])(errorResponseFields),
7
+ function handleFieldErrors(environment, fieldErrors, loggingContext) {
8
+ var _iterator = (0, _createForOfIteratorHelper2["default"])(fieldErrors),
8
9
  _step;
9
10
  try {
10
11
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
11
12
  var fieldError = _step.value;
12
- environment.relayFieldLogger(fieldError);
13
+ environment.relayFieldLogger((0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, fieldError), {}, {
14
+ uiContext: loggingContext
15
+ }));
13
16
  }
14
17
  } catch (err) {
15
18
  _iterator.e(err);
16
19
  } finally {
17
20
  _iterator.f();
18
21
  }
19
- var _iterator2 = (0, _createForOfIteratorHelper2["default"])(errorResponseFields),
22
+ var _iterator2 = (0, _createForOfIteratorHelper2["default"])(fieldErrors),
20
23
  _step2;
21
24
  try {
22
25
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
@@ -24,7 +27,7 @@ function handleFieldErrors(environment, errorResponseFields) {
24
27
  if (eventShouldThrow(_fieldError)) {
25
28
  switch (_fieldError.kind) {
26
29
  case 'relay_resolver.error':
27
- throw new Error("Relay: Resolver error at path '".concat(_fieldError.fieldPath, "' in '").concat(_fieldError.owner, "'."));
30
+ throw new Error("Relay: Resolver error at path '".concat(_fieldError.fieldPath, "' in '").concat(_fieldError.owner, "'. Message: ").concat(_fieldError.error.message));
28
31
  case 'relay_field_payload.error':
29
32
  throw new Error("Relay: Unexpected response payload - check server logs for details.");
30
33
  case 'missing_expected_data.throw':
@@ -62,9 +65,9 @@ function eventShouldThrow(event) {
62
65
  throw new Error('Relay: Unexpected event kind');
63
66
  }
64
67
  }
65
- function handlePotentialSnapshotErrors(environment, errorResponseFields) {
66
- if (errorResponseFields != null) {
67
- handleFieldErrors(environment, errorResponseFields);
68
+ function handlePotentialSnapshotErrors(environment, fieldErrors, loggingContext) {
69
+ if (fieldErrors != null) {
70
+ handleFieldErrors(environment, fieldErrors, loggingContext);
68
71
  }
69
72
  }
70
73
  module.exports = {
@@ -87,6 +87,7 @@ class ActorSpecificEnvironment implements IActorEnvironment {
87
87
  config.handlerProvider,
88
88
  defaultGetDataID,
89
89
  config.missingFieldHandlers,
90
+ this.__log,
90
91
  );
91
92
  this._defaultRenderPolicy = config.defaultRenderPolicy;
92
93
  // TODO:T92305692 Remove `options` in favor of directly using `actorIdentifier` on the environment
@@ -18,6 +18,7 @@ import type {
18
18
  FragmentType,
19
19
  HandleFieldPayload,
20
20
  HasUpdatableSpread,
21
+ LogFunction,
21
22
  MissingFieldHandler,
22
23
  RecordProxy,
23
24
  RecordSource,
@@ -53,12 +54,14 @@ class RelayRecordSourceProxy implements RecordSourceProxy {
53
54
  _invalidatedStore: boolean;
54
55
  _idsMarkedForInvalidation: DataIDSet;
55
56
  _missingFieldHandlers: $ReadOnlyArray<MissingFieldHandler>;
57
+ _log: LogFunction;
56
58
 
57
59
  constructor(
58
60
  mutator: RelayRecordSourceMutator,
59
61
  getDataID: GetDataID,
60
62
  handlerProvider?: ?HandlerProvider,
61
63
  missingFieldHandlers: $ReadOnlyArray<MissingFieldHandler>,
64
+ log: ?LogFunction,
62
65
  ) {
63
66
  this.__mutator = mutator;
64
67
  this._handlerProvider = handlerProvider || null;
@@ -67,6 +70,7 @@ class RelayRecordSourceProxy implements RecordSourceProxy {
67
70
  this._invalidatedStore = false;
68
71
  this._idsMarkedForInvalidation = new Set();
69
72
  this._missingFieldHandlers = missingFieldHandlers;
73
+ this._log = log ?? (LogEvent => {});
70
74
  }
71
75
 
72
76
  publishSource(
@@ -181,11 +181,11 @@ function updateProxyFromSelections<TData>(
181
181
  case 'ClientEdgeToServerObject':
182
182
  case 'Defer':
183
183
  case 'ModuleImport':
184
- case 'RelayLiveResolver':
185
184
  case 'RequiredField':
186
185
  case 'CatchField':
187
186
  case 'Stream':
188
187
  case 'RelayResolver':
188
+ case 'RelayLiveResolver':
189
189
  // These types of reader nodes are not currently handled.
190
190
  throw new Error(
191
191
  'Encountered an unexpected ReaderSelection variant in RelayRecordSourceProxy. This indicates a bug in Relay.',
@@ -145,13 +145,13 @@ if (__DEV__) {
145
145
  return validateModuleImport(context);
146
146
  case 'TypeDiscriminator':
147
147
  return validateAbstractKey(context, selection.abstractKey);
148
- case 'RelayResolver':
149
- case 'RelayLiveResolver':
150
148
  case 'ClientEdgeToClientObject':
151
149
  case 'LinkedHandle':
152
150
  case 'ScalarHandle':
153
151
  case 'Defer':
154
- case 'Stream': {
152
+ case 'Stream':
153
+ case 'RelayResolver':
154
+ case 'RelayLiveResolver': {
155
155
  // TODO(T35864292) - Add missing validations for these types
156
156
  return;
157
157
  }
@@ -11,6 +11,7 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ import type {OperationAvailability} from '../store/RelayStoreTypes';
14
15
  import type {RequestParameters} from '../util/RelayConcreteNode';
15
16
  import type {CacheConfig, Variables} from '../util/RelayRuntimeTypes';
16
17
  import type RelayObservable, {ObservableFromValue} from './RelayObservable';
@@ -104,6 +105,8 @@ export type ExecuteFunction = (
104
105
  logRequestInfo?: ?LogRequestInfoFunction,
105
106
  encryptedVariables?: ?string,
106
107
  preprocessResponse?: ?preprocessResponseFunction,
108
+ // Run datachecker on the current operation and returns the OperationAvailability
109
+ checkOperation?: () => OperationAvailability,
107
110
  ) => RelayObservable<GraphQLResponse>;
108
111
 
109
112
  /**
@@ -614,11 +614,7 @@ if (__DEV__) {
614
614
  // Default implementation of HostReportErrors() in development builds.
615
615
  // Can be replaced by the host application environment.
616
616
  RelayObservable.onUnhandledError((error, isUncaughtThrownError) => {
617
- declare function fail(string): void;
618
- if (typeof fail === 'function') {
619
- // In test environments (Jest), fail() immediately fails the current test.
620
- fail(String(error));
621
- } else if (isUncaughtThrownError) {
617
+ if (isUncaughtThrownError) {
622
618
  // Rethrow uncaught thrown errors on the next frame to avoid breaking
623
619
  // current logic.
624
620
  setTimeout(() => {