relay-runtime 18.1.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 (92) hide show
  1. package/experimental.js +1 -1
  2. package/experimental.js.flow +22 -9
  3. package/handlers/connection/ConnectionHandler.js.flow +6 -1
  4. package/index.js +1 -1
  5. package/index.js.flow +4 -0
  6. package/lib/experimental.js +5 -2
  7. package/lib/handlers/connection/ConnectionHandler.js +1 -1
  8. package/lib/index.js +3 -0
  9. package/lib/multi-actor-environment/ActorSpecificEnvironment.js +1 -1
  10. package/lib/mutations/RelayRecordProxy.js +14 -3
  11. package/lib/mutations/RelayRecordSourceMutator.js +17 -0
  12. package/lib/mutations/RelayRecordSourceProxy.js +2 -1
  13. package/lib/mutations/createUpdatableProxy.js +1 -1
  14. package/lib/mutations/validateMutation.js +2 -2
  15. package/lib/network/RelayObservable.js +1 -3
  16. package/lib/network/wrapNetworkWithLogObserver.js +2 -2
  17. package/lib/query/fetchQuery.js +1 -1
  18. package/lib/store/DataChecker.js +4 -5
  19. package/lib/store/OperationExecutor.js +11 -0
  20. package/lib/store/RelayModernEnvironment.js +13 -4
  21. package/lib/store/RelayModernFragmentSpecResolver.js +4 -4
  22. package/lib/store/RelayModernStore.js +43 -21
  23. package/lib/store/RelayPublishQueue.js +11 -15
  24. package/lib/store/RelayReader.js +244 -183
  25. package/lib/store/RelayReferenceMarker.js +3 -4
  26. package/lib/store/RelayResponseNormalizer.js +48 -26
  27. package/lib/store/RelayStoreSubscriptions.js +2 -2
  28. package/lib/store/RelayStoreUtils.js +8 -0
  29. package/lib/store/ResolverCache.js +1 -165
  30. package/lib/store/ResolverFragments.js +2 -2
  31. package/lib/store/createRelayLoggingContext.js +17 -0
  32. package/lib/store/generateTypenamePrefixedDataID.js +9 -0
  33. package/lib/store/live-resolvers/LiveResolverCache.js +5 -10
  34. package/lib/store/live-resolvers/resolverDataInjector.js +4 -4
  35. package/lib/store/observeFragmentExperimental.js +60 -13
  36. package/lib/store/observeQueryExperimental.js +21 -0
  37. package/lib/util/RelayFeatureFlags.js +7 -2
  38. package/lib/util/handlePotentialSnapshotErrors.js +12 -9
  39. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +1 -0
  40. package/mutations/RelayRecordProxy.js.flow +30 -3
  41. package/mutations/RelayRecordSourceMutator.js.flow +27 -0
  42. package/mutations/RelayRecordSourceProxy.js.flow +4 -0
  43. package/mutations/createUpdatableProxy.js.flow +1 -1
  44. package/mutations/validateMutation.js.flow +3 -3
  45. package/network/RelayNetworkTypes.js.flow +3 -0
  46. package/network/RelayObservable.js.flow +1 -5
  47. package/network/wrapNetworkWithLogObserver.js.flow +19 -1
  48. package/package.json +1 -1
  49. package/query/fetchQuery.js.flow +1 -1
  50. package/store/DataChecker.js.flow +5 -2
  51. package/store/OperationExecutor.js.flow +12 -1
  52. package/store/RelayExperimentalGraphResponseTransform.js.flow +4 -4
  53. package/store/RelayModernEnvironment.js.flow +22 -6
  54. package/store/RelayModernFragmentSpecResolver.js.flow +6 -6
  55. package/store/RelayModernRecord.js.flow +1 -1
  56. package/store/RelayModernSelector.js.flow +2 -0
  57. package/store/RelayModernStore.js.flow +74 -27
  58. package/store/RelayOptimisticRecordSource.js.flow +2 -0
  59. package/store/RelayPublishQueue.js.flow +32 -21
  60. package/store/RelayReader.js.flow +400 -145
  61. package/store/RelayRecordState.js.flow +1 -1
  62. package/store/RelayReferenceMarker.js.flow +3 -4
  63. package/store/RelayResponseNormalizer.js.flow +94 -62
  64. package/store/RelayStoreSubscriptions.js.flow +2 -2
  65. package/store/RelayStoreTypes.js.flow +45 -15
  66. package/store/RelayStoreUtils.js.flow +30 -1
  67. package/store/ResolverCache.js.flow +2 -271
  68. package/store/ResolverFragments.js.flow +5 -3
  69. package/store/StoreInspector.js.flow +5 -0
  70. package/store/createRelayContext.js.flow +3 -2
  71. package/store/createRelayLoggingContext.js.flow +46 -0
  72. package/store/generateTypenamePrefixedDataID.js.flow +25 -0
  73. package/store/live-resolvers/LiveResolverCache.js.flow +5 -10
  74. package/store/live-resolvers/resolverDataInjector.js.flow +10 -6
  75. package/store/observeFragmentExperimental.js.flow +82 -28
  76. package/store/observeQueryExperimental.js.flow +61 -0
  77. package/store/waitForFragmentExperimental.js.flow +4 -3
  78. package/util/NormalizationNode.js.flow +10 -1
  79. package/util/ReaderNode.js.flow +9 -3
  80. package/util/RelayConcreteNode.js.flow +3 -1
  81. package/util/RelayError.js.flow +1 -0
  82. package/util/RelayFeatureFlags.js.flow +31 -7
  83. package/util/RelayRuntimeTypes.js.flow +17 -3
  84. package/util/getPaginationVariables.js.flow +2 -0
  85. package/util/handlePotentialSnapshotErrors.js.flow +24 -12
  86. package/util/registerEnvironmentWithDevTools.js.flow +4 -2
  87. package/util/withProvidedVariables.js.flow +1 -0
  88. package/util/withStartAndDuration.js.flow +3 -0
  89. package/relay-runtime-experimental.js +0 -4
  90. package/relay-runtime-experimental.min.js +0 -9
  91. package/relay-runtime.js +0 -4
  92. package/relay-runtime.min.js +0 -9
@@ -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
+ };
@@ -5,7 +5,6 @@ var RelayFeatureFlags = {
5
5
  ENABLE_RELAY_RESOLVERS: false,
6
6
  ENABLE_GETFRAGMENTIDENTIFIER_OPTIMIZATION: false,
7
7
  ENABLE_FRIENDLY_QUERY_NAME_GQL_URL: false,
8
- ENABLE_LOAD_QUERY_REQUEST_DEDUPING: true,
9
8
  ENABLE_DO_NOT_WRAP_LIVE_QUERY: false,
10
9
  ENABLE_NOTIFY_SUBSCRIPTION: false,
11
10
  BATCH_ASYNC_MODULE_UPDATES_FN: null,
@@ -13,6 +12,8 @@ var RelayFeatureFlags = {
13
12
  MAX_DATA_ID_LENGTH: null,
14
13
  STRING_INTERN_LEVEL: 0,
15
14
  LOG_MISSING_RECORDS_IN_PROD: false,
15
+ ENABLE_STORE_ID_COLLISION_LOGGING: false,
16
+ ENABLE_NONCOMPLIANT_ERROR_HANDLING_ON_LISTS: false,
16
17
  ENABLE_LOOSE_SUBSCRIPTION_ATTRIBUTION: false,
17
18
  ENABLE_OPERATION_TRACKER_OPTIMISTIC_UPDATES: false,
18
19
  ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE: 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
- AVOID_CYCLES_IN_RESOLVER_NOTIFICATION: false
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,9 +27,9 @@ 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
- throw new Error("Relay: Unexpected response payload - this object includes an errors property in which you can access the underlying errors");
32
+ throw new Error("Relay: Unexpected response payload - check server logs for details.");
30
33
  case 'missing_expected_data.throw':
31
34
  throw new Error("Relay: Missing expected data at path '".concat(_fieldError.fieldPath, "' in '").concat(_fieldError.owner, "'."));
32
35
  case 'missing_required_field.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
@@ -11,6 +11,7 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ import type {TRelayFieldError} from '../store/RelayErrorTrie';
14
15
  import type {RecordProxy} from '../store/RelayStoreTypes';
15
16
  import type {Arguments} from '../store/RelayStoreUtils';
16
17
  import type {DataID} from '../util/RelayRuntimeTypes';
@@ -65,22 +66,48 @@ class RelayRecordProxy implements RecordProxy {
65
66
  return this._mutator.getValue(this._dataID, storageKey);
66
67
  }
67
68
 
68
- setValue(value: mixed, name: string, args?: ?Arguments): RecordProxy {
69
+ setValue(
70
+ value: mixed,
71
+ name: string,
72
+ args?: ?Arguments,
73
+ errors?: ?$ReadOnlyArray<TRelayFieldError>,
74
+ ): RecordProxy {
69
75
  invariant(
70
76
  isValidLeafValue(value),
71
77
  'RelayRecordProxy#setValue(): Expected a scalar or array of scalars, ' +
72
78
  'got `%s`.',
73
79
  JSON.stringify(value),
74
80
  );
75
- return this.setValue__UNSAFE(value, name, args);
81
+
82
+ return this.setValue__UNSAFE(value, name, args, errors);
83
+ }
84
+
85
+ getErrors(
86
+ name: string,
87
+ args?: ?Arguments,
88
+ ): ?$ReadOnlyArray<TRelayFieldError> {
89
+ const storageKey = getStableStorageKey(name, args);
90
+ return this._mutator.getErrors(this._dataID, storageKey);
76
91
  }
77
92
 
78
93
  // This is used in the typesafe updaters.
79
94
  // We already validated that the value has the correct type
80
95
  // so it should be safe to store complex structures as scalar values (custom scalars)
81
- setValue__UNSAFE(value: mixed, name: string, args?: ?Arguments): RecordProxy {
96
+ setValue__UNSAFE(
97
+ value: mixed,
98
+ name: string,
99
+ args?: ?Arguments,
100
+ errors?: ?$ReadOnlyArray<TRelayFieldError>,
101
+ ): RecordProxy {
82
102
  const storageKey = getStableStorageKey(name, args);
83
103
  this._mutator.setValue(this._dataID, storageKey, value);
104
+ if (errors != null) {
105
+ if (errors.length === 0) {
106
+ this._mutator.setErrors(this._dataID, storageKey);
107
+ } else {
108
+ this._mutator.setErrors(this._dataID, storageKey, errors);
109
+ }
110
+ }
84
111
  return this;
85
112
  }
86
113
 
@@ -11,6 +11,7 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ import type {TRelayFieldError} from '../store/RelayErrorTrie';
14
15
  import type {RecordState} from '../store/RelayRecordState';
15
16
  import type {
16
17
  MutableRecordSource,
@@ -179,6 +180,32 @@ class RelayRecordSourceMutator {
179
180
  RelayModernRecord.setValue(sinkRecord, storageKey, value);
180
181
  }
181
182
 
183
+ getErrors(
184
+ dataID: DataID,
185
+ storageKey: string,
186
+ ): ?$ReadOnlyArray<TRelayFieldError> {
187
+ for (let ii = 0; ii < this.__sources.length; ii++) {
188
+ const record = this.__sources[ii].get(dataID);
189
+ if (record) {
190
+ const value = RelayModernRecord.getErrors(record, storageKey);
191
+ if (value !== undefined) {
192
+ return value;
193
+ }
194
+ } else if (record === null) {
195
+ return null;
196
+ }
197
+ }
198
+ }
199
+
200
+ setErrors(
201
+ dataID: DataID,
202
+ storageKey: string,
203
+ errors?: $ReadOnlyArray<TRelayFieldError>,
204
+ ): void {
205
+ const sinkRecord = this._getSinkRecord(dataID);
206
+ RelayModernRecord.setErrors(sinkRecord, storageKey, errors);
207
+ }
208
+
182
209
  getLinkedRecordID(dataID: DataID, storageKey: string): ?DataID {
183
210
  for (let ii = 0; ii < this.__sources.length; ii++) {
184
211
  const record = this.__sources[ii].get(dataID);
@@ -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(() => {
@@ -12,12 +12,17 @@
12
12
  'use strict';
13
13
  import type ActorSpecificEnvironment from '../multi-actor-environment/ActorSpecificEnvironment';
14
14
  import type RelayModernEnvironment from '../store/RelayModernEnvironment';
15
+ import type {
16
+ LogRequestInfoFunction,
17
+ OperationAvailability,
18
+ } from '../store/RelayStoreTypes';
15
19
  import type {RequestParameters} from '../util/RelayConcreteNode';
16
20
  import type {CacheConfig, Variables} from '../util/RelayRuntimeTypes';
17
21
  import type {
18
22
  GraphQLResponse,
19
23
  INetwork,
20
24
  UploadableMap,
25
+ preprocessResponseFunction,
21
26
  } from './RelayNetworkTypes';
22
27
  import type RelayObservable from './RelayObservable';
23
28
  import type {Subscription} from './RelayObservable';
@@ -42,6 +47,10 @@ function wrapNetworkWithLogObserver(
42
47
  variables: Variables,
43
48
  cacheConfig: CacheConfig,
44
49
  uploadables?: ?UploadableMap,
50
+ _?: ?LogRequestInfoFunction,
51
+ encryptedVariables?: ?string,
52
+ preprocessResponse?: ?preprocessResponseFunction,
53
+ checkOperation?: () => OperationAvailability,
45
54
  ): RelayObservable<GraphQLResponse> {
46
55
  const networkRequestId = generateID();
47
56
  const logObserver = {
@@ -89,7 +98,16 @@ function wrapNetworkWithLogObserver(
89
98
  });
90
99
  };
91
100
  return network
92
- .execute(params, variables, cacheConfig, uploadables, logRequestInfo)
101
+ .execute(
102
+ params,
103
+ variables,
104
+ cacheConfig,
105
+ uploadables,
106
+ logRequestInfo,
107
+ encryptedVariables,
108
+ preprocessResponse,
109
+ checkOperation,
110
+ )
93
111
  .do(logObserver);
94
112
  },
95
113
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "relay-runtime",
3
3
  "description": "A core runtime for building GraphQL-driven applications.",
4
- "version": "18.1.0",
4
+ "version": "19.0.0",
5
5
  "keywords": [
6
6
  "graphql",
7
7
  "relay"
@@ -138,7 +138,7 @@ function fetchQuery<TVariables: Variables, TData, TRawResponse>(
138
138
  const fetchPolicy = options?.fetchPolicy ?? 'network-only';
139
139
 
140
140
  function readData(snapshot: Snapshot): TData {
141
- handlePotentialSnapshotErrors(environment, snapshot.errorResponseFields);
141
+ handlePotentialSnapshotErrors(environment, snapshot.fieldErrors);
142
142
  /* $FlowFixMe[incompatible-return] we assume readData returns the right
143
143
  * data just having written it from network or checked availability. */
144
144
  return snapshot.data;
@@ -90,6 +90,7 @@ function check(
90
90
  operationLoader,
91
91
  getDataID,
92
92
  shouldProcessClientComponents,
93
+ log,
93
94
  );
94
95
  const result = checker.check(node, dataID);
95
96
  if (log != null) {
@@ -123,6 +124,7 @@ class DataChecker {
123
124
  ActorIdentifier,
124
125
  [RelayRecordSourceMutator, RelayRecordSourceProxy],
125
126
  >;
127
+ _log: ?LogFunction;
126
128
 
127
129
  constructor(
128
130
  getSourceForActor: (actorIdentifier: ActorIdentifier) => RecordSource,
@@ -135,6 +137,7 @@ class DataChecker {
135
137
  operationLoader: ?OperationLoader,
136
138
  getDataID: GetDataID,
137
139
  shouldProcessClientComponents: ?boolean,
140
+ log: ?LogFunction,
138
141
  ) {
139
142
  this._getSourceForActor = getSourceForActor;
140
143
  this._getTargetForActor = getTargetForActor;
@@ -152,6 +155,7 @@ class DataChecker {
152
155
  this._recordWasMissing = false;
153
156
  this._variables = variables;
154
157
  this._shouldProcessClientComponents = shouldProcessClientComponents;
158
+ this._log = log;
155
159
  }
156
160
 
157
161
  _getMutatorAndRecordProxyForActor(
@@ -170,6 +174,7 @@ class DataChecker {
170
174
  this._getDataID,
171
175
  undefined,
172
176
  this._handlers,
177
+ this._log,
173
178
  );
174
179
  tuple = [mutator, recordSourceProxy];
175
180
  this._mutatorRecordSourceProxyCache.set(actorIdentifier, tuple);
@@ -449,8 +454,6 @@ class DataChecker {
449
454
  this._traverseSelections(selection.fragment.selections, dataID);
450
455
  break;
451
456
  case 'RelayResolver':
452
- this._checkResolver(selection, dataID);
453
- break;
454
457
  case 'RelayLiveResolver':
455
458
  this._checkResolver(selection, dataID);
456
459
  break;
@@ -245,6 +245,12 @@ class Executor<TMutation: MutationParameters> {
245
245
  cacheConfig: this._operation.request.cacheConfig ?? {},
246
246
  });
247
247
  },
248
+ unsubscribe: () => {
249
+ this._log({
250
+ name: 'execute.unsubscribe',
251
+ executeId: this._executeId,
252
+ });
253
+ },
248
254
  });
249
255
 
250
256
  if (
@@ -293,7 +299,7 @@ class Executor<TMutation: MutationParameters> {
293
299
  }
294
300
 
295
301
  _updateActiveState(): void {
296
- let activeState;
302
+ let activeState: ActiveState;
297
303
  switch (this._state) {
298
304
  case 'started': {
299
305
  activeState = 'active';
@@ -606,6 +612,7 @@ class Executor<TMutation: MutationParameters> {
606
612
  {
607
613
  actorIdentifier: this._actorIdentifier,
608
614
  getDataID: this._getDataID,
615
+ log: this._log,
609
616
  path: [],
610
617
  shouldProcessClientComponents: this._shouldProcessClientComponents,
611
618
  treatMissingFieldsAsNull,
@@ -715,6 +722,7 @@ class Executor<TMutation: MutationParameters> {
715
722
  {
716
723
  actorIdentifier: this._actorIdentifier,
717
724
  getDataID: this._getDataID,
725
+ log: this._log,
718
726
  path: followupPayload.path,
719
727
  treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
720
728
  shouldProcessClientComponents: this._shouldProcessClientComponents,
@@ -797,6 +805,7 @@ class Executor<TMutation: MutationParameters> {
797
805
  {
798
806
  actorIdentifier: this._actorIdentifier,
799
807
  getDataID: this._getDataID,
808
+ log: this._log,
800
809
  path: [],
801
810
  treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
802
811
  shouldProcessClientComponents: this._shouldProcessClientComponents,
@@ -1253,6 +1262,7 @@ class Executor<TMutation: MutationParameters> {
1253
1262
  {
1254
1263
  actorIdentifier: this._actorIdentifier,
1255
1264
  getDataID: this._getDataID,
1265
+ log: this._log,
1256
1266
  path: placeholder.path,
1257
1267
  treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
1258
1268
  shouldProcessClientComponents: this._shouldProcessClientComponents,
@@ -1480,6 +1490,7 @@ class Executor<TMutation: MutationParameters> {
1480
1490
  const relayPayload = this._normalizeResponse(response, selector, typeName, {
1481
1491
  actorIdentifier: this._actorIdentifier,
1482
1492
  getDataID: this._getDataID,
1493
+ log: this._log,
1483
1494
  path: [...normalizationPath, responseKey, String(itemIndex)],
1484
1495
  treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
1485
1496
  shouldProcessClientComponents: this._shouldProcessClientComponents,
@@ -222,10 +222,10 @@ export class GraphModeNormalizer {
222
222
  $streamID,
223
223
  __id: dataID,
224
224
  __typename: ROOT_TYPE,
225
- };
225
+ } as RecordChunk;
226
226
  yield {
227
227
  $kind: 'Complete',
228
- };
228
+ } as CompleteChunk;
229
229
  }
230
230
 
231
231
  *_flushFields(
@@ -247,9 +247,9 @@ export class GraphModeNormalizer {
247
247
  __typename: typename,
248
248
  __id: cacheKey,
249
249
  $streamID,
250
- };
250
+ } as RecordChunk;
251
251
  } else if (Object.keys(fields).length > 0) {
252
- yield {...fields, $kind: 'Extend', $streamID};
252
+ yield {...fields, $kind: 'Extend', $streamID} as ExtendChunk;
253
253
  }
254
254
  return $streamID;
255
255
  }