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
@@ -12,12 +12,12 @@
12
12
  'use strict';
13
13
 
14
14
  import type {Fragment} from '../../util/RelayRuntimeTypes';
15
- import type {FragmentType} from '../RelayStoreTypes';
15
+ import type {FragmentType, ResolverContext} from '../RelayStoreTypes';
16
16
 
17
17
  const {readFragment} = require('../ResolverFragments');
18
18
  const invariant = require('invariant');
19
19
 
20
- type ResolverFn = ($FlowFixMe, ?$FlowFixMe) => mixed;
20
+ type ResolverFn = ($FlowFixMe, ?$FlowFixMe, ResolverContext) => mixed;
21
21
 
22
22
  /**
23
23
  *
@@ -40,7 +40,11 @@ function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
40
40
  isRequiredField?: boolean,
41
41
  ): (fragmentKey: TFragmentType, args: mixed) => mixed {
42
42
  const resolverFn: ResolverFn = _resolverFn;
43
- return (fragmentKey: TFragmentType, args: mixed): mixed => {
43
+ return (
44
+ fragmentKey: TFragmentType,
45
+ args: mixed,
46
+ resolverContext: ResolverContext,
47
+ ): mixed => {
44
48
  const data = readFragment(fragment, fragmentKey);
45
49
  if (fieldName != null) {
46
50
  if (data == null) {
@@ -52,7 +56,7 @@ function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
52
56
  fragment.name,
53
57
  );
54
58
  } else {
55
- return resolverFn(null, args);
59
+ return resolverFn(null, args, resolverContext); // TODO: This statement does not seem to be covered by a test?
56
60
  }
57
61
  }
58
62
 
@@ -70,7 +74,7 @@ function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
70
74
  }
71
75
 
72
76
  // $FlowFixMe[invalid-computed-prop]
73
- return resolverFn(data[fieldName], args);
77
+ return resolverFn(data[fieldName], args, resolverContext);
74
78
  } else {
75
79
  // If both `data` and `fieldName` is available, we expect the
76
80
  // `fieldName` field in the `data` object.
@@ -83,7 +87,7 @@ function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
83
87
  }
84
88
  } else {
85
89
  // By default we will pass the full set of the fragment data to the resolver
86
- return resolverFn(data, args);
90
+ return resolverFn(null, args, resolverContext); // TODO: This statement does not seem to be covered by a test?
87
91
  }
88
92
  };
89
93
  }
@@ -9,7 +9,7 @@
9
9
  * @oncall relay
10
10
  */
11
11
 
12
- import type {RequestDescriptor} from './RelayStoreTypes';
12
+ import type {PluralReaderSelector, RequestDescriptor} from './RelayStoreTypes';
13
13
  import type {
14
14
  Fragment,
15
15
  FragmentType,
@@ -20,8 +20,8 @@ import type {
20
20
  } from 'relay-runtime';
21
21
 
22
22
  const Observable = require('../network/RelayObservable');
23
+ const {getObservableForActiveRequest} = require('../query/fetchQueryInternal');
23
24
  const {getFragment} = require('../query/GraphQLTag');
24
- const getPendingOperationsForFragment = require('../util/getPendingOperationsForFragment');
25
25
  const {
26
26
  handlePotentialSnapshotErrors,
27
27
  } = require('../util/handlePotentialSnapshotErrors');
@@ -47,8 +47,7 @@ export type HasSpread<TFragmentType> = {
47
47
 
48
48
  /**
49
49
  * EXPERIMENTAL: This API is experimental and does not yet support all Relay
50
- * features. Notably, it does not correectly handle plural fragments or some
51
- * features of Relay Resolvers.
50
+ * features. Notably, it does not correctly handle some features of Relay Resolvers.
52
51
  *
53
52
  * Given a fragment and a fragment reference, returns a promise that resolves
54
53
  * once the fragment data is available, or rejects if the fragment has an error.
@@ -63,7 +62,9 @@ export type HasSpread<TFragmentType> = {
63
62
  async function waitForFragmentData<TFragmentType: FragmentType, TData>(
64
63
  environment: IEnvironment,
65
64
  fragment: Fragment<TFragmentType, TData>,
66
- fragmentRef: HasSpread<TFragmentType>,
65
+ fragmentRef:
66
+ | HasSpread<TFragmentType>
67
+ | $ReadOnlyArray<HasSpread<TFragmentType>>,
67
68
  ): Promise<TData> {
68
69
  let subscription: ?Subscription;
69
70
 
@@ -94,13 +95,14 @@ async function waitForFragmentData<TFragmentType: FragmentType, TData>(
94
95
  declare function observeFragment<TFragmentType: FragmentType, TData>(
95
96
  environment: IEnvironment,
96
97
  fragment: Fragment<TFragmentType, TData>,
97
- fragmentRef: HasSpread<TFragmentType>,
98
+ fragmentRef:
99
+ | HasSpread<TFragmentType>
100
+ | $ReadOnlyArray<HasSpread<TFragmentType>>,
98
101
  ): Observable<FragmentState<TData>>;
99
102
 
100
103
  /**
101
104
  * EXPERIMENTAL: This API is experimental and does not yet support all Relay
102
- * features. Notably, it does not correectly handle plural fragments or some
103
- * features of Relay Resolvers.
105
+ * features. Notably, it does not correctly handle some features of Relay Resolvers.
104
106
  *
105
107
  * Given a fragment and a fragment reference, returns an observable that emits
106
108
  * the state of the fragment over time. The observable will emit the following
@@ -114,7 +116,7 @@ function observeFragment<TFragmentType: FragmentType, TData>(
114
116
  environment: IEnvironment,
115
117
  fragment: Fragment<TFragmentType, TData>,
116
118
  fragmentRef: mixed,
117
- ): Observable<FragmentState<TData>> {
119
+ ): mixed {
118
120
  const fragmentNode = getFragment(fragment);
119
121
  const fragmentSelector = getSelector(fragmentNode, fragmentRef);
120
122
  invariant(
@@ -124,24 +126,19 @@ function observeFragment<TFragmentType: FragmentType, TData>(
124
126
  invariant(fragmentSelector != null, 'Expected a selector, got null.');
125
127
  switch (fragmentSelector.kind) {
126
128
  case 'SingularReaderSelector':
127
- return observeSelector(environment, fragment, fragmentSelector);
129
+ return observeSingularSelector(environment, fragment, fragmentSelector);
128
130
  case 'PluralReaderSelector': {
129
- // TODO: We could use something like this RXJS's combineLatest to create
130
- // an observable for each selector and merge them.
131
- // https://github.com/ReactiveX/rxjs/blob/master/packages/rxjs/src/internal/observable/combineLatest.ts
132
- //
133
- // Note that this problem is a bit tricky because Relay currently only
134
- // lets you subscribe at a singular fragment granularity. This makes it
135
- // hard to batch updates such that when a store update causes multiple
136
- // fragments to change, we can only publish a single update to the
137
- // fragment owner.
138
- invariant(false, 'Plural fragments are not supported');
131
+ return observePluralSelector(
132
+ environment,
133
+ (fragment: $FlowFixMe),
134
+ fragmentSelector,
135
+ );
139
136
  }
140
137
  }
141
138
  invariant(false, 'Unsupported fragment selector kind');
142
139
  }
143
140
 
144
- function observeSelector<TFragmentType: FragmentType, TData>(
141
+ function observeSingularSelector<TFragmentType: FragmentType, TData>(
145
142
  environment: IEnvironment,
146
143
  fragmentNode: Fragment<TFragmentType, TData>,
147
144
  fragmentSelector: SingularReaderSelector,
@@ -173,6 +170,49 @@ function observeSelector<TFragmentType: FragmentType, TData>(
173
170
  });
174
171
  }
175
172
 
173
+ function observePluralSelector<
174
+ TFragmentType: FragmentType,
175
+ TData: Array<mixed>,
176
+ >(
177
+ environment: IEnvironment,
178
+ fragmentNode: Fragment<TFragmentType, TData>,
179
+ fragmentSelector: PluralReaderSelector,
180
+ ): Observable<FragmentState<TData>> {
181
+ const snapshots = fragmentSelector.selectors.map(selector =>
182
+ environment.lookup(selector),
183
+ );
184
+
185
+ return Observable.create(sink => {
186
+ // This array is mutable since each subscription updates the array in place.
187
+ const states = snapshots.map((snapshot, index) =>
188
+ snapshotToFragmentState(
189
+ environment,
190
+ fragmentNode,
191
+ fragmentSelector.selectors[index].owner,
192
+ snapshot,
193
+ ),
194
+ );
195
+
196
+ sink.next((mergeFragmentStates(states): $FlowFixMe));
197
+
198
+ const subscriptions = snapshots.map((snapshot, index) =>
199
+ environment.subscribe(snapshot, latestSnapshot => {
200
+ states[index] = snapshotToFragmentState(
201
+ environment,
202
+ fragmentNode,
203
+ fragmentSelector.selectors[index].owner,
204
+ latestSnapshot,
205
+ );
206
+ // This doesn't batch updates, so it will notify the subscriber multiple times
207
+ // if a store update impacting multiple items in the list is published.
208
+ sink.next((mergeFragmentStates(states): $FlowFixMe));
209
+ }),
210
+ );
211
+
212
+ return () => subscriptions.forEach(subscription => subscription.dispose());
213
+ });
214
+ }
215
+
176
216
  function snapshotToFragmentState<TFragmentType: FragmentType, TData>(
177
217
  environment: IEnvironment,
178
218
  fragmentNode: Fragment<TFragmentType, TData>,
@@ -201,18 +241,18 @@ function snapshotToFragmentState<TFragmentType: FragmentType, TData>(
201
241
  }
202
242
 
203
243
  if (snapshot.isMissingData) {
204
- const pendingOperations = getPendingOperationsForFragment(
205
- environment,
206
- fragmentNode,
207
- owner,
208
- );
209
- if (pendingOperations != null) {
244
+ if (
245
+ getObservableForActiveRequest(environment, owner) != null ||
246
+ environment
247
+ .getOperationTracker()
248
+ .getPendingOperationsAffectingOwner(owner) != null
249
+ ) {
210
250
  return {state: 'loading'};
211
251
  }
212
252
  }
213
253
 
214
254
  try {
215
- handlePotentialSnapshotErrors(environment, snapshot.errorResponseFields);
255
+ handlePotentialSnapshotErrors(environment, snapshot.fieldErrors);
216
256
  } catch (error) {
217
257
  return {error, state: 'error'};
218
258
  }
@@ -229,6 +269,20 @@ function snapshotToFragmentState<TFragmentType: FragmentType, TData>(
229
269
  return {state: 'ok', value: (snapshot.data: $FlowFixMe)};
230
270
  }
231
271
 
272
+ function mergeFragmentStates<T>(
273
+ states: $ReadOnlyArray<FragmentState<T>>,
274
+ ): FragmentState<Array<T>> {
275
+ const value = [];
276
+ for (const state of states) {
277
+ if (state.state === 'ok') {
278
+ value.push(state.value);
279
+ } else {
280
+ return state;
281
+ }
282
+ }
283
+ return {state: 'ok', value};
284
+ }
285
+
232
286
  module.exports = {
233
287
  observeFragment,
234
288
  waitForFragmentData,
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and 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
+ * @flow strict-local
8
+ * @format
9
+ * @oncall relay
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ import type RelayObservable from '../network/RelayObservable';
15
+ import type {FragmentState} from './observeFragmentExperimental';
16
+ import type {OperationDescriptor} from './RelayStoreTypes';
17
+ import type {Fragment, IEnvironment, Query, Variables} from 'relay-runtime';
18
+
19
+ const {observeFragment} = require('./observeFragmentExperimental');
20
+ const {createOperationDescriptor} = require('./RelayModernOperationDescriptor');
21
+
22
+ /**
23
+ * This function returns an observable that can be used to subscribe to the data
24
+ * contained in a query. It does not return the full response shape, but rather
25
+ * the contents of the query body minus any fragment spreads. If you wish to
26
+ * read the contents of a fragment spread into this query you may pass the
27
+ * object into which the fragment was spread to `observeFragment`.
28
+ *
29
+ * NOTE: `observeQuery` assumes that you have already fetched and retained the
30
+ * query via some other means, such as `fetchQuery`.
31
+ *
32
+ * This feature is still experimental and does not properly handle some resolver
33
+ * features such as client-to-server edges.
34
+ */
35
+ function observeQuery<TVariables: Variables, TData>(
36
+ environment: IEnvironment,
37
+ gqlQuery: Query<TVariables, TData>,
38
+ variables: TVariables,
39
+ ): RelayObservable<FragmentState<TData>> {
40
+ const operation: OperationDescriptor = createOperationDescriptor(
41
+ gqlQuery,
42
+ variables,
43
+ );
44
+
45
+ const rootFragmentRef: $FlowFixMe = {
46
+ __id: operation.fragment.dataID,
47
+ __fragments: {
48
+ [operation.fragment.node.name]: operation.request.variables,
49
+ },
50
+ __fragmentOwner: operation.request,
51
+ };
52
+
53
+ const fragmentNode: Fragment<$FlowFixMe, TData> = (operation.request.node
54
+ .fragment: $FlowFixMe);
55
+
56
+ return observeFragment(environment, fragmentNode, rootFragmentRef);
57
+ }
58
+
59
+ module.exports = {
60
+ observeQuery,
61
+ };
@@ -21,8 +21,7 @@ const {observeFragment} = require('./observeFragmentExperimental');
21
21
 
22
22
  /**
23
23
  * EXPERIMENTAL: This API is experimental and does not yet support all Relay
24
- * features. Notably, it does not correectly handle plural fragments or some
25
- * features of Relay Resolvers.
24
+ * features. Notably, it does not correctly handle some features of Relay Resolvers.
26
25
  *
27
26
  * Given a fragment and a fragment reference, returns a promise that resolves
28
27
  * once the fragment data is available, or rejects if the fragment has an error.
@@ -37,7 +36,9 @@ const {observeFragment} = require('./observeFragmentExperimental');
37
36
  async function waitForFragmentData<TFragmentType: FragmentType, TData>(
38
37
  environment: IEnvironment,
39
38
  fragment: Fragment<TFragmentType, TData>,
40
- fragmentRef: HasSpread<TFragmentType>,
39
+ fragmentRef:
40
+ | HasSpread<TFragmentType>
41
+ | $ReadOnlyArray<HasSpread<TFragmentType>>,
41
42
  ): Promise<TData> {
42
43
  let subscription: ?Subscription;
43
44
 
@@ -12,7 +12,7 @@
12
12
  'use strict';
13
13
 
14
14
  import type {ResolverFunction, ResolverModule} from './ReaderNode';
15
- import type {ConcreteRequest} from './RelayConcreteNode';
15
+ import type {ConcreteRequest, ProvidedVariableType} from './RelayConcreteNode';
16
16
  import type {JSResourceReference} from 'JSResourceReference';
17
17
 
18
18
  /**
@@ -28,6 +28,7 @@ export type NormalizationOperation = {
28
28
  +[string]: $ReadOnlyArray<string>,
29
29
  },
30
30
  +use_exec_time_resolvers?: boolean,
31
+ +exec_time_resolvers_enabled_provider?: ProvidedVariableType,
31
32
  };
32
33
 
33
34
  export type NormalizationHandle =
@@ -39,6 +39,8 @@ export type NormalizationRootNode =
39
39
  | ConcreteRequest
40
40
  | NormalizationSplitOperation;
41
41
 
42
+ export type ProvidedVariableType = {get(): mixed};
43
+
42
44
  export type ProvidedVariablesType = {+[key: string]: {get(): mixed}};
43
45
 
44
46
  /**
@@ -25,6 +25,7 @@ function createError(
25
25
  String(messageParams[index++]),
26
26
  );
27
27
  const err = new Error(message);
28
+ // $FlowFixMe[unsafe-object-assign]
28
29
  const error = Object.assign((err: any), {
29
30
  name,
30
31
  messageFormat,
@@ -26,6 +26,7 @@ export type FeatureFlags = {
26
26
  STRING_INTERN_LEVEL: number,
27
27
  LOG_MISSING_RECORDS_IN_PROD: boolean,
28
28
  ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE: boolean,
29
+ ENABLE_UI_CONTEXT_ON_RELAY_LOGGER: boolean,
29
30
 
30
31
  // Some GraphQL servers are noncompliant with the GraphQL specification and
31
32
  // return an empty list instead of null when there is a field error on a list.
@@ -58,6 +59,18 @@ export type FeatureFlags = {
58
59
  // Adds a prefix to the storage key of read time resolvers. This is used to
59
60
  // disambiguate the same resolver being used at both read time and exec time.
60
61
  ENABLE_READ_TIME_RESOLVER_STORAGE_KEY_PREFIX: boolean,
62
+
63
+ // Enable the fix for usePaginationFragment stucking in loading state
64
+ ENABLE_USE_PAGINATION_IS_LOADING_FIX: boolean,
65
+
66
+ // Enable logging an ID collision in the Relay store
67
+ ENABLE_STORE_ID_COLLISION_LOGGING: boolean,
68
+
69
+ // Throw on nested store updates
70
+ DISALLOW_NESTED_UPDATES: boolean,
71
+
72
+ // Enable prefixing of DataID in the store with __typename
73
+ ENABLE_TYPENAME_PREFIXED_DATA_ID: boolean,
61
74
  };
62
75
 
63
76
  const RelayFeatureFlags: FeatureFlags = {
@@ -72,6 +85,7 @@ const RelayFeatureFlags: FeatureFlags = {
72
85
  MAX_DATA_ID_LENGTH: null,
73
86
  STRING_INTERN_LEVEL: 0,
74
87
  LOG_MISSING_RECORDS_IN_PROD: false,
88
+ ENABLE_STORE_ID_COLLISION_LOGGING: false,
75
89
  ENABLE_NONCOMPLIANT_ERROR_HANDLING_ON_LISTS: false,
76
90
  ENABLE_LOOSE_SUBSCRIPTION_ATTRIBUTION: false,
77
91
  ENABLE_OPERATION_TRACKER_OPTIMISTIC_UPDATES: false,
@@ -81,6 +95,10 @@ const RelayFeatureFlags: FeatureFlags = {
81
95
  ENABLE_CYLE_DETECTION_IN_VARIABLES: false,
82
96
  ENABLE_ACTIVITY_COMPATIBILITY: false,
83
97
  ENABLE_READ_TIME_RESOLVER_STORAGE_KEY_PREFIX: true,
98
+ ENABLE_USE_PAGINATION_IS_LOADING_FIX: false,
99
+ DISALLOW_NESTED_UPDATES: false,
100
+ ENABLE_TYPENAME_PREFIXED_DATA_ID: false,
101
+ ENABLE_UI_CONTEXT_ON_RELAY_LOGGER: false,
84
102
  };
85
103
 
86
104
  module.exports = RelayFeatureFlags;
@@ -53,9 +53,10 @@ export type VariablesOf<T: OperationType> = T['variables'];
53
53
  * state of any configured response cache.
54
54
  * - `poll`: causes a query to live update by polling at the specified interval
55
55
  * in milliseconds. (This value will be passed to setTimeout.)
56
- * - `liveConfigId`: causes a query to live update by calling GraphQLLiveQuery,
57
- * it represents a configuration of gateway when doing live query
58
- * - `onSubscribe`: Not in use.
56
+ * - `liveConfigId`: Makes a query live by sending through RTI stack.
57
+ * - `onSubscribe`: Callback to be called when a live query stream is started.
58
+ * - `onPause`: Callback to be called when a live query stream is paused, e.g. due to a network disconnection.
59
+ * - `onResume`: Callback to be called when a live query stream is resumed, e.g. from a network disconnection.
59
60
  * - `metadata`: user-supplied metadata.
60
61
  * - `transactionId`: a user-supplied value, intended for use as a unique id for
61
62
  * a given instance of executing an operation.
@@ -65,6 +66,8 @@ export type CacheConfig = {
65
66
  poll?: ?number,
66
67
  liveConfigId?: ?string,
67
68
  onSubscribe?: () => void,
69
+ onResume?: (pauseTimeMs: number) => void,
70
+ onPause?: (mqttConnectionIsOk: boolean, internetIsOk: boolean) => void,
68
71
  metadata?: {[key: string]: mixed, ...},
69
72
  transactionId?: ?string,
70
73
  };
@@ -56,6 +56,7 @@ function getPaginationVariables(
56
56
  ...baseVariables,
57
57
  ...extraVariables,
58
58
  [backwardMetadata.cursor]: cursor,
59
+ // $FlowFixMe[incompatible-type]
59
60
  [backwardMetadata.count]: count,
60
61
  };
61
62
  if (forwardMetadata && forwardMetadata.cursor) {
@@ -92,6 +93,7 @@ function getPaginationVariables(
92
93
  ...baseVariables,
93
94
  ...extraVariables,
94
95
  [forwardMetadata.cursor]: cursor,
96
+ // $FlowFixMe[incompatible-type]
95
97
  [forwardMetadata.count]: count,
96
98
  };
97
99
  if (backwardMetadata && backwardMetadata.cursor) {
@@ -12,8 +12,8 @@
12
12
  'use strict';
13
13
 
14
14
  import type {
15
- ErrorResponseField,
16
- ErrorResponseFields,
15
+ FieldError,
16
+ FieldErrors,
17
17
  IEnvironment,
18
18
  } from '../store/RelayStoreTypes';
19
19
 
@@ -21,21 +21,32 @@ const invariant = require('invariant');
21
21
 
22
22
  function handleFieldErrors(
23
23
  environment: IEnvironment,
24
- errorResponseFields: ErrorResponseFields,
24
+ fieldErrors: FieldErrors,
25
+ loggingContext: mixed | void,
25
26
  ) {
26
- for (const fieldError of errorResponseFields) {
27
+ for (const fieldError of fieldErrors) {
27
28
  // First we log all events. Note that the logger may opt to throw its own
28
29
  // error here if it wants to throw an error that is better integrated into
29
30
  // site's error handling infrastructure.
30
- environment.relayFieldLogger(fieldError);
31
+
32
+ // Awkward. We don't want to attach the ui context in RelayReader where we
33
+ // create the event, but it means we need to add it here instead of just
34
+ // passing the event through.
35
+
36
+ environment.relayFieldLogger({
37
+ // the uiContext on fieldError undefined *always*,
38
+ ...fieldError,
39
+ // and this is where we assign loggingContext to uiContext to populate it
40
+ uiContext: loggingContext,
41
+ });
31
42
  }
32
43
 
33
- for (const fieldError of errorResponseFields) {
44
+ for (const fieldError of fieldErrors) {
34
45
  if (eventShouldThrow(fieldError)) {
35
46
  switch (fieldError.kind) {
36
47
  case 'relay_resolver.error':
37
48
  throw new Error(
38
- `Relay: Resolver error at path '${fieldError.fieldPath}' in '${fieldError.owner}'.`,
49
+ `Relay: Resolver error at path '${fieldError.fieldPath}' in '${fieldError.owner}'. Message: ${fieldError.error.message}`,
39
50
  );
40
51
  case 'relay_field_payload.error':
41
52
  throw new Error(
@@ -63,7 +74,7 @@ function handleFieldErrors(
63
74
  }
64
75
  }
65
76
 
66
- function eventShouldThrow(event: ErrorResponseField): boolean {
77
+ function eventShouldThrow(event: FieldError): boolean {
67
78
  switch (event.kind) {
68
79
  case 'relay_resolver.error':
69
80
  case 'relay_field_payload.error':
@@ -82,14 +93,15 @@ function eventShouldThrow(event: ErrorResponseField): boolean {
82
93
 
83
94
  function handlePotentialSnapshotErrors(
84
95
  environment: IEnvironment,
85
- errorResponseFields: ?ErrorResponseFields,
96
+ fieldErrors: ?FieldErrors,
97
+ loggingContext: mixed | void,
86
98
  ) {
87
99
  /**
88
100
  * Inside handleFieldErrors, we check for throwOnFieldError - but this fn logs the error anyway by default
89
101
  * which is why this still should run in any case there's errors.
90
102
  */
91
- if (errorResponseFields != null) {
92
- handleFieldErrors(environment, errorResponseFields);
103
+ if (fieldErrors != null) {
104
+ handleFieldErrors(environment, fieldErrors, loggingContext);
93
105
  }
94
106
  }
95
107
 
@@ -19,8 +19,10 @@ function registerEnvironmentWithDevTools(environment: IEnvironment): void {
19
19
  const _global =
20
20
  typeof global !== 'undefined'
21
21
  ? global
22
- : typeof window !== 'undefined'
23
- ? window
22
+ : // $FlowFixMe[cannot-resolve-name]
23
+ typeof window !== 'undefined'
24
+ ? // $FlowFixMe[cannot-resolve-name]
25
+ window
24
26
  : undefined;
25
27
 
26
28
  // $FlowFixMe[incompatible-use] D61394600
@@ -30,6 +30,7 @@ function withProvidedVariables(
30
30
  ): Variables {
31
31
  if (providedVariables != null) {
32
32
  const operationVariables: {[string]: mixed} = {};
33
+ // $FlowFixMe[unsafe-object-assign]
33
34
  Object.assign(operationVariables, userSuppliedVariables);
34
35
  Object.keys(providedVariables).forEach((varName: string) => {
35
36
  const providerFunction = providedVariables[varName].get;
@@ -12,11 +12,14 @@
12
12
  'use strict';
13
13
 
14
14
  const isPerformanceNowAvailable =
15
+ // $FlowFixMe[cannot-resolve-name]
15
16
  typeof window !== 'undefined' &&
17
+ // $FlowFixMe[cannot-resolve-name]
16
18
  typeof window?.performance?.now === 'function';
17
19
 
18
20
  function currentTimestamp(): number {
19
21
  if (isPerformanceNowAvailable) {
22
+ // $FlowFixMe[cannot-resolve-name]
20
23
  return window.performance.now();
21
24
  }
22
25
  return Date.now();
@@ -1,4 +0,0 @@
1
- /**
2
- * Relay v18.2.0
3
- */
4
- !function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r(require("@babel/runtime/helpers/asyncToGenerator"),require("@babel/runtime/helpers/createForOfIteratorHelper"),require("@babel/runtime/helpers/defineProperty"),require("@babel/runtime/helpers/interopRequireDefault"),require("@babel/runtime/helpers/objectSpread2"),require("@babel/runtime/helpers/toConsumableArray"),require("fbjs/lib/areEqual"),require("fbjs/lib/warning"),require("invariant")):"function"==typeof define&&define.amd?define(["@babel/runtime/helpers/asyncToGenerator","@babel/runtime/helpers/createForOfIteratorHelper","@babel/runtime/helpers/defineProperty","@babel/runtime/helpers/interopRequireDefault","@babel/runtime/helpers/objectSpread2","@babel/runtime/helpers/toConsumableArray","fbjs/lib/areEqual","fbjs/lib/warning","invariant"],r):"object"==typeof exports?exports.ReactRelayExperimental=r(require("@babel/runtime/helpers/asyncToGenerator"),require("@babel/runtime/helpers/createForOfIteratorHelper"),require("@babel/runtime/helpers/defineProperty"),require("@babel/runtime/helpers/interopRequireDefault"),require("@babel/runtime/helpers/objectSpread2"),require("@babel/runtime/helpers/toConsumableArray"),require("fbjs/lib/areEqual"),require("fbjs/lib/warning"),require("invariant")):e.ReactRelayExperimental=r(e["@babel/runtime/helpers/asyncToGenerator"],e["@babel/runtime/helpers/createForOfIteratorHelper"],e["@babel/runtime/helpers/defineProperty"],e["@babel/runtime/helpers/interopRequireDefault"],e["@babel/runtime/helpers/objectSpread2"],e["@babel/runtime/helpers/toConsumableArray"],e["fbjs/lib/areEqual"],e["fbjs/lib/warning"],e.invariant)}(self,((e,r,t,n,a,o,i,u,l)=>(()=>{"use strict";var s={649:(e,r,t)=>{var n=t(662),a=t(696).observeFragment,o=t(461).waitForFragmentData;e.exports={resolverDataInjector:n,isValueResult:function(e){return!0===e.ok},isErrorResult:function(e){return!1===e.ok},observeFragment:a,waitForFragmentData:o}},60:(e,r,t)=>{var n=t(571),a=function(e,r){},o=function(){function e(e){if(!e||"function"!=typeof e)throw new Error("Source must be a Function: "+String(e));this._source=e}e.create=function(r){return new e(r)},e.onUnhandledError=function(e){a=e},e.from=function(e){return function(e){return"object"==typeof e&&null!==e&&"function"==typeof e.subscribe}(e)?i(e):n(e)?u(e):l(e)};var r=e.prototype;return r.catch=function(r){var t=this;return e.create((function(e){var n;return t.subscribe({start:function(e){n=e},next:e.next,complete:e.complete,error:function(t){try{r(t).subscribe({start:function(e){n=e},next:e.next,complete:e.complete,error:e.error})}catch(r){e.error(r,!0)}}}),function(){return n.unsubscribe()}}))},r.concat=function(r){var t=this;return e.create((function(e){var n;return t.subscribe({start:function(e){n=e},next:e.next,error:e.error,complete:function(){n=r.subscribe(e)}}),function(){n&&n.unsubscribe()}}))},r.do=function(r){var t=this;return e.create((function(e){var n=function(t){return function(){try{r[t]&&r[t].apply(r,arguments)}catch(e){a(e,!0)}e[t]&&e[t].apply(e,arguments)}};return t.subscribe({start:n("start"),next:n("next"),error:n("error"),complete:n("complete"),unsubscribe:n("unsubscribe")})}))},r.finally=function(r){var t=this;return e.create((function(e){var n=t.subscribe(e);return function(){n.unsubscribe(),r()}}))},r.ifEmpty=function(r){var t=this;return e.create((function(e){var n,a=!1;return n=t.subscribe({next:function(r){a=!0,e.next(r)},error:e.error,complete:function(){a?e.complete():n=r.subscribe(e)}}),function(){n&&n.unsubscribe()}}))},r.subscribe=function(e){if(!e||"object"!=typeof e)throw new Error("Observer must be an Object with callbacks: "+String(e));return function(e,r){var t,n=!1,o=function(e){return Object.defineProperty(e,"closed",{get:function(){return n}})};function i(){if(t){if(t.unsubscribe)t.unsubscribe();else try{t()}catch(e){a(e,!0)}t=void 0}}var u=o({unsubscribe:function(){if(!n){n=!0;try{r.unsubscribe&&r.unsubscribe(u)}catch(e){a(e,!0)}finally{i()}}}});try{r.start&&r.start(u)}catch(e){a(e,!0)}if(n)return u;var l=o({next:function(e){if(!n&&r.next)try{r.next(e)}catch(e){a(e,!0)}},error:function(e,t){if(n||!r.error)n=!0,a(e,t||!1),i();else{n=!0;try{r.error(e)}catch(e){a(e,!0)}finally{i()}}},complete:function(){if(!n){n=!0;try{r.complete&&r.complete()}catch(e){a(e,!0)}finally{i()}}}});try{t=e(l)}catch(e){l.error(e,!0)}if(void 0!==t&&"function"!=typeof t&&(!t||"function"!=typeof t.unsubscribe))throw new Error("Returned cleanup function which cannot be called: "+String(t));return n&&i(),u}(this._source,e)},r.map=function(r){var t=this;return e.create((function(e){var n=t.subscribe({complete:e.complete,error:e.error,next:function(t){try{var n=r(t);e.next(n)}catch(r){e.error(r,!0)}}});return function(){n.unsubscribe()}}))},r.mergeMap=function(r){var t=this;return e.create((function(n){var a=[];function o(e){this._sub=e,a.push(e)}function i(){a.splice(a.indexOf(this._sub),1),0===a.length&&n.complete()}return t.subscribe({start:o,next:function(t){try{n.closed||e.from(r(t)).subscribe({start:o,next:n.next,error:n.error,complete:i})}catch(e){n.error(e,!0)}},error:n.error,complete:i}),function(){a.forEach((function(e){return e.unsubscribe()})),a.length=0}}))},r.poll=function(r){var t=this;if("number"!=typeof r||r<=0)throw new Error("RelayObservable: Expected pollInterval to be positive, got: "+r);return e.create((function(e){var n,a;return function o(){n=t.subscribe({next:e.next,error:e.error,complete:function(){a=setTimeout(o,r)}})}(),function(){clearTimeout(a),n.unsubscribe()}}))},r.toPromise=function(){var e=this;return new Promise((function(r,t){var n=!1;e.subscribe({next:function(e){n||(n=!0,r(e))},error:t,complete:r})}))},e}();function i(e){return e instanceof o?e:o.create((function(r){return e.subscribe(r)}))}function u(e){return o.create((function(r){e.then((function(e){r.next(e),r.complete()}),r.error)}))}function l(e){return o.create((function(r){r.next(e),r.complete()}))}o.onUnhandledError((function(e,r){"function"==typeof fail?fail(String(e)):r?setTimeout((function(){throw e})):"undefined"!=typeof console&&console.error("RelayObservable: Unhandled Error",e)})),e.exports=o},634:(e,r,t)=>{var n=t(775),a=t(56),o=t(446);function i(e){var r=e;return"function"==typeof r?(r=r(),o(!1,"RelayGraphQLTag: node `%s` unexpectedly wrapped in a function.","Fragment"===r.kind?r.name:r.operation.name)):r.default&&(r=r.default),r}function u(e){var r=i(e);return"object"==typeof r&&null!==r&&r.kind===n.FRAGMENT}function l(e){var r=i(e);return"object"==typeof r&&null!==r&&r.kind===n.REQUEST}function s(e){var r=i(e);return"object"==typeof r&&null!==r&&r.kind===n.UPDATABLE_QUERY}function c(e){var r=i(e);return"object"==typeof r&&null!==r&&r.kind===n.INLINE_DATA_FRAGMENT}function f(e){var r=i(e);return u(r)||a(!1,"GraphQLTag: Expected a fragment, got `%s`.",JSON.stringify(r)),r}e.exports={getFragment:f,getNode:i,getPaginationFragment:function(e){var r,t=f(e),n=null===(r=t.metadata)||void 0===r?void 0:r.refetch,a=null==n?void 0:n.connection;return null===n||"object"!=typeof n||null===a||"object"!=typeof a?null:t},getRefetchableFragment:function(e){var r,t=f(e),n=null===(r=t.metadata)||void 0===r?void 0:r.refetch;return null===n||"object"!=typeof n?null:t},getRequest:function(e){var r=i(e);return l(r)||a(!1,"GraphQLTag: Expected a request, got `%s`.",JSON.stringify(r)),r},getUpdatableQuery:function(e){var r=i(e);return s(r)||a(!1,"GraphQLTag: Expected a request, got `%s`.",JSON.stringify(r)),r},getInlineDataFragment:function(e){var r=i(e);return c(r)||a(!1,"GraphQLTag: Expected an inline data fragment, got `%s`.",JSON.stringify(r)),r},graphql:function(e){a(!1,"graphql: Unexpected invocation at runtime. Either the Babel transform was not set up, or it failed to identify this call site. Make sure it is being used verbatim as `graphql`. Note also that there cannot be a space between graphql and the backtick that follows.")},isFragment:u,isRequest:l,isUpdatableQuery:s,isInlineDataFragment:c}},367:(e,r,t)=>{var n=t(60),a=t(153),o=t(56),i="function"==typeof WeakMap?new WeakMap:new Map;function u(e,r,t){return n.create((function(i){var u=s(e),l=u.get(r);return l||t().finally((function(){return u.delete(r)})).subscribe({start:function(e){l={identifier:r,subject:new a,subjectForInFlightStatus:new a,subscription:e,promise:null},u.set(r,l)},next:function(e){var t=c(u,r);t.subject.next(e),t.subjectForInFlightStatus.next(e)},error:function(e){var t=c(u,r);t.subject.error(e),t.subjectForInFlightStatus.error(e)},complete:function(){var e=c(u,r);e.subject.complete(),e.subjectForInFlightStatus.complete()},unsubscribe:function(e){var t=c(u,r);t.subject.unsubscribe(),t.subjectForInFlightStatus.unsubscribe()}}),null==l&&o(!1,"[fetchQueryInternal] fetchQueryDeduped: Expected `start` to be called synchronously"),function(e,r){return n.create((function(t){var n=r.subject.subscribe(t);return function(){n.unsubscribe();var t=e.get(r.identifier);if(t){var a=t.subscription;null!=a&&0===t.subject.getObserverCount()&&(a.unsubscribe(),e.delete(r.identifier))}}}))}(u,l).subscribe(i)}))}function l(e,r,t){return n.create((function(r){var n=t.subjectForInFlightStatus.subscribe({error:r.error,next:function(n){e.isRequestActive(t.identifier)?r.next():r.complete()},complete:r.complete,unsubscribe:r.complete});return function(){n.unsubscribe()}}))}function s(e){var r=i.get(e);if(null!=r)return r;var t=new Map;return i.set(e,t),t}function c(e,r){var t=e.get(r);return null==t&&o(!1,"[fetchQueryInternal] getCachedRequest: Expected request to be cached"),t}e.exports={fetchQuery:function(e,r){return u(e,r.request.identifier,(function(){return e.execute({operation:r})}))},fetchQueryDeduped:u,getPromiseForActiveRequest:function(e,r){var t=s(e).get(r.identifier);return t&&e.isRequestActive(t.identifier)?new Promise((function(r,n){var a=!1;l(e,0,t).subscribe({complete:r,error:n,next:function(e){a&&r(e)}}),a=!0})):null},getObservableForActiveRequest:function(e,r){var t=s(e).get(r.identifier);return t&&e.isRequestActive(t.identifier)?l(e,0,t):null}}},129:(e,r,t)=>{var n=(0,t(275).default)(t(175)),a=t(165).getArgumentValues,o=t(56);e.exports={getLocalVariables:function(e,r,t){if(null==r)return e;var o=(0,n.default)({},e),i=t?a(t,e):{};return r.forEach((function(e){var r,t=null!==(r=i[e.name])&&void 0!==r?r:e.defaultValue;o[e.name]=t})),o},getFragmentVariables:function(e,r,t){return null==e.argumentDefinitions?t:(e.argumentDefinitions.forEach((function(i){if(!t.hasOwnProperty(i.name))switch(a=a||(0,n.default)({},t),i.kind){case"LocalArgument":a[i.name]=i.defaultValue;break;case"RootArgument":if(!r.hasOwnProperty(i.name)){a[i.name]=void 0;break}a[i.name]=r[i.name];break;default:o(!1,"RelayConcreteVariables: Unexpected node kind `%s` in fragment `%s`.",i.kind,e.name)}})),a||t);var a},getOperationVariables:function(e,r,t){var n={};return e.argumentDefinitions.forEach((function(e){var r=e.defaultValue;null!=t[e.name]&&(r=t[e.name]),n[e.name]=r})),null!=r&&Object.keys(r).forEach((function(e){n[e]=r[e].get()})),n}}},256:(e,r,t)=>{var n=t(129).getFragmentVariables,a=t(165),o=a.CLIENT_EDGE_TRAVERSAL_PATH,i=a.FRAGMENT_OWNER_KEY,u=a.FRAGMENT_POINTER_IS_WITHIN_UNMATCHED_TYPE_REFINEMENT,l=a.FRAGMENTS_KEY,s=a.ID_KEY,c=t(125),f=t(56),d=t(446);function p(e,r){("object"!=typeof r||null===r||Array.isArray(r))&&f(!1,"RelayModernSelector: Expected value for fragment `%s` to be an object, got `%s`.",e.name,JSON.stringify(r));var t=r[s],a=r[l],c=r[i],p=r[o];if("string"==typeof t&&"object"==typeof a&&null!==a&&"object"==typeof a[e.name]&&null!==a[e.name]&&"object"==typeof c&&null!==c&&(null==p||Array.isArray(p))){var b=c,m=p,g=a[e.name];return R(e,t,n(e,b.variables,g),b,!0===g[u],m)}var v=JSON.stringify(r);return v.length>499&&(v=v.substr(0,498)+"…"),d(!1,"RelayModernSelector: Expected object to contain data for fragment `%s`, got `%s`. Make sure that the parent operation/fragment included fragment `...%s` without `@relay(mask: false)`.",e.name,v,e.name),null}function b(e,r){var t=null;return r.forEach((function(r,n){var a=null!=r?p(e,r):null;null!=a&&(t=t||[]).push(a)})),null==t?null:{kind:"PluralReaderSelector",selectors:t}}function m(e,r){return null==r?r:e.metadata&&!0===e.metadata.plural?(Array.isArray(r)||f(!1,"RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.",e.name,JSON.stringify(r),e.name),b(e,r)):(Array.isArray(r)&&f(!1,"RelayModernSelector: Expected value for fragment `%s` to be an object, got `%s`. Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.",e.name,JSON.stringify(r),e.name),p(e,r))}function g(e,r){return null==r?r:e.metadata&&!0===e.metadata.plural?(Array.isArray(r)||f(!1,"RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.",e.name,JSON.stringify(r),e.name),function(e,r){var t=null;return r.forEach((function(r){var n=null!=r?v(e,r):null;null!=n&&(t=t||[]).push(n)})),t}(e,r)):(Array.isArray(r)&&f(!1,"RelayModernFragmentSpecResolver: Expected value for fragment `%s` to be an object, got `%s`. Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.",e.name,JSON.stringify(r),e.name),v(e,r))}function v(e,r){("object"!=typeof r||null===r||Array.isArray(r))&&f(!1,"RelayModernSelector: Expected value for fragment `%s` to be an object, got `%s`.",e.name,JSON.stringify(r));var t=r[s];return"string"==typeof t?t:(d(!1,"RelayModernSelector: Expected object to contain data for fragment `%s`, got `%s`. Make sure that the parent operation/fragment included fragment `...%s` without `@relay(mask: false)`, or `null` is passed as the fragment reference for `%s` if it's conditonally included and the condition isn't met.",e.name,JSON.stringify(r),e.name,e.name),null)}function h(e,r){var t;return null==r?{}:!0===(null===(t=e.metadata)||void 0===t?void 0:t.plural)?(Array.isArray(r)||f(!1,"RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.",e.name,JSON.stringify(r),e.name),y(e,r)):(Array.isArray(r)&&f(!1,"RelayModernFragmentSpecResolver: Expected value for fragment `%s` to be an object, got `%s`. Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.",e.name,JSON.stringify(r),e.name),E(e,r)||{})}function E(e,r){var t=p(e,r);return t?t.variables:null}function y(e,r){var t={};return r.forEach((function(r,n){if(null!=r){var a=E(e,r);null!=a&&Object.assign(t,a)}})),t}function _(e,r){return e.dataID===r.dataID&&e.node===r.node&&c(e.variables,r.variables)&&((t=e.owner)===(n=r.owner)||t.identifier===n.identifier&&c(t.cacheConfig,n.cacheConfig))&&e.isWithinUnmatchedTypeRefinement===r.isWithinUnmatchedTypeRefinement&&function(e,r){if(e===r)return!0;if(null==e||null==r||e.length!==r.length)return!1;for(var t=e.length;t--;){var n=e[t],a=r[t];if(n!==a&&(null==n||null==a||n.clientEdgeDestinationID!==a.clientEdgeDestinationID||n.readerClientEdge!==a.readerClientEdge))return!1}return!0}(e.clientEdgeTraversalPath,r.clientEdgeTraversalPath);var t,n}function R(e,r,t,n){var a=arguments.length>5?arguments[5]:void 0;return{kind:"SingularReaderSelector",dataID:r,isWithinUnmatchedTypeRefinement:arguments.length>4&&void 0!==arguments[4]&&arguments[4],clientEdgeTraversalPath:null!=a?a:null,node:e,variables:t,owner:n}}e.exports={areEqualSelectors:function(e,r){return e===r||(null==e?null==r:null==r?null==e:"SingularReaderSelector"===e.kind&&"SingularReaderSelector"===r.kind?_(e,r):"PluralReaderSelector"===e.kind&&"PluralReaderSelector"===r.kind&&e.selectors.length===r.selectors.length&&e.selectors.every((function(e,t){return _(e,r.selectors[t])})))},createReaderSelector:R,createNormalizationSelector:function(e,r,t){return{dataID:r,node:e,variables:t}},getDataIDsFromFragment:g,getDataIDsFromObject:function(e,r){var t={};for(var n in e)if(e.hasOwnProperty(n)){var a=e[n],o=r[n];t[n]=g(a,o)}return t},getSingularSelector:p,getPluralSelector:b,getSelector:m,getSelectorsFromObject:function(e,r){var t={};for(var n in e)if(e.hasOwnProperty(n)){var a=e[n],o=r[n];t[n]=m(a,o)}return t},getVariablesFromSingularFragment:E,getVariablesFromPluralFragment:y,getVariablesFromFragment:h,getVariablesFromObject:function(e,r){var t={};for(var n in e)if(e.hasOwnProperty(n)){var a=h(e[n],r[n]);Object.assign(t,a)}return t}}},165:(e,r,t)=>{var n=(0,t(275).default)(t(642)),a=t(330),o=t(775),i=t(94).stableCopy,u=t(56),l=o.VARIABLE,s=o.LITERAL,c=o.OBJECT_VALUE,f=o.LIST_VALUE;function d(e,r){if(e.kind===l)return function(e,r){return r.hasOwnProperty(e)||u(!1,"getVariableValue(): Undefined variable `%s`.",e),i(r[e])}(e.variableName,r);if(e.kind===s)return e.value;if(e.kind===c){var t={};return e.fields.forEach((function(e){t[e.name]=d(e,r)})),t}if(e.kind===f){var n=[];return e.items.forEach((function(e){null!=e&&n.push(d(e,r))})),n}}function p(e,r,t){var n={};return t&&(n[m.FRAGMENT_POINTER_IS_WITHIN_UNMATCHED_TYPE_REFINEMENT]=!0),e&&e.forEach((function(e){n[e.name]=d(e,r)})),n}function b(e,r){if(!r)return e;var t=[];for(var n in r)if(r.hasOwnProperty(n)){var a,o=r[n];null!=o&&t.push(n+":"+(null!==(a=JSON.stringify(o))&&void 0!==a?a:"undefined"))}return 0===t.length?e:e+"(".concat(t.join(","),")")}var m={ACTOR_IDENTIFIER_KEY:"__actorIdentifier",CLIENT_EDGE_TRAVERSAL_PATH:"__clientEdgeTraversalPath",FRAGMENTS_KEY:"__fragments",FRAGMENT_OWNER_KEY:"__fragmentOwner",FRAGMENT_POINTER_IS_WITHIN_UNMATCHED_TYPE_REFINEMENT:"$isWithinUnmatchedTypeRefinement",FRAGMENT_PROP_NAME_KEY:"__fragmentPropName",MODULE_COMPONENT_KEY:"__module_component",ERRORS_KEY:"__errors",ID_KEY:"__id",REF_KEY:"__ref",REFS_KEY:"__refs",ROOT_ID:"client:root",ROOT_TYPE:"__Root",TYPENAME_KEY:"__typename",INVALIDATED_AT_KEY:"__invalidated_at",RELAY_RESOLVER_VALUE_KEY:"__resolverValue",RELAY_RESOLVER_INVALIDATION_KEY:"__resolverValueMayBeInvalid",RELAY_RESOLVER_SNAPSHOT_KEY:"__resolverSnapshot",RELAY_RESOLVER_ERROR_KEY:"__resolverError",RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS:"__resolverOutputTypeRecordIDs",formatStorageKey:b,getArgumentValue:d,getArgumentValues:p,getHandleStorageKey:function(e,r){var t=e.dynamicKey,o=e.handle,i=e.key,u=e.name,l=e.args,s=e.filters,c=a(o,i,u),f=null;return l&&s&&0!==l.length&&0!==s.length&&(f=l.filter((function(e){return s.indexOf(e.name)>-1}))),t&&(f=null!=f?[t].concat((0,n.default)(f)):[t]),null===f?c:b(c,p(f,r))},getStorageKey:function(e,r){if(e.storageKey)return e.storageKey;var t=function(e){var r,t;return"RelayResolver"===e.kind||"RelayLiveResolver"===e.kind?null==e.args?null===(t=e.fragment)||void 0===t?void 0:t.args:null==(null===(r=e.fragment)||void 0===r?void 0:r.args)?e.args:e.args.concat(e.fragment.args):void 0===e.args?void 0:e.args}(e),n=e.name;return t&&0!==t.length?b(n,p(t,r)):n},getStableStorageKey:function(e,r){return b(e,i(r))},getModuleComponentKey:function(e){return"".concat("__module_component_").concat(e)},getModuleOperationKey:function(e){return"".concat("__module_operation_").concat(e)}};e.exports=m},890:(e,r,t)=>{var n=t(634).getFragment,a=t(222).eventShouldThrow,o=t(256).getSelector,i=t(56),u=[],l={};e.exports={readFragment:function(e,r){if(!u.length)throw new Error("readFragment should be called only from within a Relay Resolver function.");var t=u[u.length-1],s=n(e),c=o(s,r);null==c&&i(!1,"Expected a selector for the fragment of the resolver ".concat(s.name,", but got null.")),"SingularReaderSelector"!==c.kind&&i(!1,"Expected a singular reader selector for the fragment of the resolver ".concat(s.name,", but it was plural."));var f=t.getDataForResolverFragment(c,r),d=f.data,p=f.isMissingData,b=f.errorResponseFields;if(p||null!=b&&b.some(a))throw l;return d},withResolverContext:function(e,r){u.push(e);try{return r()}finally{u.pop()}},RESOLVER_FRAGMENT_ERRORED_SENTINEL:l}},662:(e,r,t)=>{var n=t(890).readFragment,a=t(56);e.exports=function(e,r,t,o){var i=r;return function(r,u){var l=n(e,r);if(null==t)return i(l,u);if(null==l){if(!0!==o)return i(null,u);a(!1,"Expected required resolver field `%s` in fragment `%s` to be present. But resolvers fragment data is null/undefined.",t,e.name)}if(t in l)return!0===o&&null==l[t]&&a(!1,"Expected required resolver field `%s` in fragment `%s` to be non-null.",t,e.name),i(l[t],u);a(!1,"Missing field `%s` in fragment `%s` in resolver response.",t,e.name)}}},696:(e,r,t)=>{var n=t(314).default,a=t(60),o=t(634).getFragment,i=t(250),u=t(222).handlePotentialSnapshotErrors,l=t(256).getSelector,s=t(56);function c(){return(c=n((function*(e,r,t){var n;try{var a,o=yield new Promise((function(a,o){n=f(e,r,t).subscribe({next:function(e){"ok"===e.state?a(e.value):"error"===e.state&&o(e.error)}})}));return null===(a=n)||void 0===a||a.unsubscribe(),o}catch(e){var i;throw null===(i=n)||void 0===i||i.unsubscribe(),e}}))).apply(this,arguments)}function f(e,r,t){var n,i=o(r),u=l(i,t);switch(null!=(null===(n=i.metadata)||void 0===n?void 0:n.hasClientEdges)&&s(!1,"Client edges aren't supported yet."),null==u&&s(!1,"Expected a selector, got null."),u.kind){case"SingularReaderSelector":return function(e,r,t){var n=e.lookup(t);return a.create((function(a){a.next(d(e,r,t.owner,n));var o=e.subscribe(n,(function(n){a.next(d(e,r,t.owner,n))}));return function(){return o.dispose()}}))}(e,r,u);case"PluralReaderSelector":s(!1,"Plural fragments are not supported")}s(!1,"Unsupported fragment selector kind")}function d(e,r,t,n){var a=null!=n.missingLiveResolverFields&&n.missingLiveResolverFields.length>0,o=null!=n.missingClientEdges&&n.missingClientEdges.length>0;if(a||o)return{state:"loading"};if(n.isMissingData&&null!=i(e,r,t))return{state:"loading"};try{u(e,n.errorResponseFields)}catch(e){return{error:e,state:"error"}}return null==n.data&&s(!1,"Expected data to be non-null."),{state:"ok",value:n.data}}e.exports={observeFragment:f,waitForFragmentData:function(e,r,t){return c.apply(this,arguments)}}},461:(e,r,t)=>{var n=t(314).default,a=t(696).observeFragment;function o(){return(o=n((function*(e,r,t){var n;try{var o,i=yield new Promise((function(o,i){n=a(e,r,t).subscribe({next:function(e){"ok"===e.state?o(e.value):"error"===e.state&&i(e.error)}})}));return null===(o=n)||void 0===o||o.unsubscribe(),i}catch(e){var u;throw null===(u=n)||void 0===u||u.unsubscribe(),e}}))).apply(this,arguments)}e.exports={waitForFragmentData:function(e,r,t){return o.apply(this,arguments)}}},775:e=>{e.exports={ACTOR_CHANGE:"ActorChange",CATCH_FIELD:"CatchField",CONDITION:"Condition",CLIENT_COMPONENT:"ClientComponent",CLIENT_EDGE_TO_SERVER_OBJECT:"ClientEdgeToServerObject",CLIENT_EDGE_TO_CLIENT_OBJECT:"ClientEdgeToClientObject",CLIENT_EXTENSION:"ClientExtension",DEFER:"Defer",CONNECTION:"Connection",FRAGMENT:"Fragment",FRAGMENT_SPREAD:"FragmentSpread",INLINE_DATA_FRAGMENT_SPREAD:"InlineDataFragmentSpread",INLINE_DATA_FRAGMENT:"InlineDataFragment",INLINE_FRAGMENT:"InlineFragment",LINKED_FIELD:"LinkedField",LINKED_HANDLE:"LinkedHandle",LITERAL:"Literal",LIST_VALUE:"ListValue",LOCAL_ARGUMENT:"LocalArgument",MODULE_IMPORT:"ModuleImport",ALIASED_FRAGMENT_SPREAD:"AliasedFragmentSpread",ALIASED_INLINE_FRAGMENT_SPREAD:"AliasedInlineFragmentSpread",RELAY_RESOLVER:"RelayResolver",RELAY_LIVE_RESOLVER:"RelayLiveResolver",REQUIRED_FIELD:"RequiredField",OBJECT_VALUE:"ObjectValue",OPERATION:"Operation",REQUEST:"Request",ROOT_ARGUMENT:"RootArgument",SCALAR_FIELD:"ScalarField",SCALAR_HANDLE:"ScalarHandle",SPLIT_OPERATION:"SplitOperation",STREAM:"Stream",TYPE_DISCRIMINATOR:"TypeDiscriminator",UPDATABLE_QUERY:"UpdatableQuery",VARIABLE:"Variable"}},204:e=>{e.exports={DEFAULT_HANDLE_KEY:""}},153:(e,r,t)=>{var n=t(275).default,a=n(t(765)),o=n(t(311)),i=t(60),u=t(56),l=function(){function e(){var e=this;(0,o.default)(this,"_complete",!1),(0,o.default)(this,"_events",[]),(0,o.default)(this,"_sinks",new Set),(0,o.default)(this,"_subscription",[]),this._observable=i.create((function(r){e._sinks.add(r);for(var t=e._events,n=0;n<t.length&&!r.closed;n++){var a=t[n];switch(a.kind){case"complete":r.complete();break;case"error":r.error(a.error);break;case"next":r.next(a.data);break;default:a.kind,u(!1,"RelayReplaySubject: Unknown event kind `%s`.",a.kind)}}return function(){e._sinks.delete(r)}}))}var r=e.prototype;return r.complete=function(){!0!==this._complete&&(this._complete=!0,this._events.push({kind:"complete"}),this._sinks.forEach((function(e){return e.complete()})))},r.error=function(e){!0!==this._complete&&(this._complete=!0,this._events.push({kind:"error",error:e}),this._sinks.forEach((function(r){return r.error(e)})))},r.next=function(e){!0!==this._complete&&(this._events.push({kind:"next",data:e}),this._sinks.forEach((function(r){return r.next(e)})))},r.subscribe=function(e){var r=this._observable.subscribe(e);return this._subscription.push(r),r},r.unsubscribe=function(){var e,r=(0,a.default)(this._subscription);try{for(r.s();!(e=r.n()).done;)e.value.unsubscribe()}catch(e){r.e(e)}finally{r.f()}this._subscription=[]},r.getObserverCount=function(){return this._sinks.size},e}();e.exports=l},250:(e,r,t)=>{var n=t(367).getPromiseForActiveRequest;e.exports=function(e,r,t){var a,o,i=[],u=n(e,t);if(null!=u)i=[t];else{var l,s,c=e.getOperationTracker().getPendingOperationsAffectingOwner(t);i=null!==(l=null==c?void 0:c.pendingOperations)&&void 0!==l?l:[],u=null!==(s=null==c?void 0:c.promise)&&void 0!==s?s:null}if(!u)return null;var f=null!==(a=null===(o=i)||void 0===o?void 0:o.map((function(e){return e.node.params.name})).join(","))&&void 0!==a?a:null;null!=f&&0!==f.length||(f="Unknown pending operation");var d=r.name,p=f===d?"Relay(".concat(f,")"):"Relay(".concat(f,":").concat(d,")");return u.displayName=p,e.__log({name:"pendingoperation.found",fragment:r,fragmentOwner:t,pendingOperations:i}),{promise:u,pendingOperations:i}}},330:(e,r,t)=>{var n=t(204).DEFAULT_HANDLE_KEY,a=t(56);e.exports=function(e,r,t){return r&&r!==n?"__".concat(r,"_").concat(e):(null==t&&a(!1,"getRelayHandleKey: Expected either `fieldName` or `key` in `handle` to be provided"),"__".concat(t,"_").concat(e))}},222:(e,r,t)=>{var n=(0,t(275).default)(t(765)),a=t(56);function o(e){switch(e.kind){case"relay_resolver.error":case"relay_field_payload.error":return e.shouldThrow&&!e.handled;case"missing_expected_data.throw":case"missing_required_field.throw":return!e.handled;case"missing_required_field.log":case"missing_expected_data.log":return!1;default:throw e.kind,new Error("Relay: Unexpected event kind")}}e.exports={handlePotentialSnapshotErrors:function(e,r){null!=r&&function(e,r){var t,i=(0,n.default)(r);try{for(i.s();!(t=i.n()).done;){var u=t.value;e.relayFieldLogger(u)}}catch(e){i.e(e)}finally{i.f()}var l,s=(0,n.default)(r);try{for(s.s();!(l=s.n()).done;){var c=l.value;if(o(c))switch(c.kind){case"relay_resolver.error":throw new Error("Relay: Resolver error at path '".concat(c.fieldPath,"' in '").concat(c.owner,"'."));case"relay_field_payload.error":throw new Error("Relay: Unexpected response payload - check server logs for details.");case"missing_expected_data.throw":throw new Error("Relay: Missing expected data at path '".concat(c.fieldPath,"' in '").concat(c.owner,"'."));case"missing_required_field.throw":throw new Error("Relay: Missing @required value at path '".concat(c.fieldPath,"' in '").concat(c.owner,"'."));case"missing_required_field.log":case"missing_expected_data.log":break;default:c.kind,a(!1,"Relay: Unexpected event kind: %s",c.kind)}}}catch(e){s.e(e)}finally{s.f()}}(e,r)},eventShouldThrow:o}},571:e=>{e.exports=function(e){return null!=e&&"object"==typeof e&&"function"==typeof e.then}},94:e=>{e.exports={stableCopy:function e(r){if(!r||"object"!=typeof r)return r;if(Array.isArray(r))return r.map(e);for(var t=Object.keys(r).sort(),n={},a=0;a<t.length;a++)n[t[a]]=e(r[t[a]]);return n},hasCycle:function e(r){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:new Set;if(!r||"object"!=typeof r)return!1;if(t.has(r))return!0;var n=new Set(t);return n.add(r),(Array.isArray(r)?r:Object.values(r)).some((function(r){return e(r,n)}))}}},314:r=>{r.exports=e},765:e=>{e.exports=r},311:e=>{e.exports=t},275:e=>{e.exports=n},175:e=>{e.exports=a},642:e=>{e.exports=o},125:e=>{e.exports=i},446:e=>{e.exports=u},56:e=>{e.exports=l}},c={};return function e(r){var t=c[r];if(void 0!==t)return t.exports;var n=c[r]={exports:{}};return s[r](n,n.exports,e),n.exports}(649)})()));