relay-runtime 20.1.1 → 21.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 (262) hide show
  1. package/experimental.js +1 -1
  2. package/experimental.js.flow +8 -8
  3. package/handlers/connection/ConnectionHandler.js.flow +5 -5
  4. package/handlers/connection/ConnectionInterface.js.flow +1 -1
  5. package/index.js +1 -1
  6. package/index.js.flow +125 -62
  7. package/lib/experimental.js +3 -3
  8. package/lib/index.js +105 -57
  9. package/lib/multi-actor-environment/ActorIdentifier.js +2 -2
  10. package/lib/multi-actor-environment/MultiActorEnvironment.js +3 -1
  11. package/lib/mutations/commitMutation.js +8 -8
  12. package/lib/mutations/validateMutation.js +4 -4
  13. package/lib/query/GraphQLTag.js +3 -3
  14. package/lib/query/fetchQuery.js +15 -3
  15. package/lib/store/DataChecker.js +38 -4
  16. package/lib/store/NormalizationEngine.js +373 -0
  17. package/lib/store/OperationExecutor.js +172 -113
  18. package/lib/store/RelayConcreteVariables.js +1 -1
  19. package/lib/store/RelayErrorTrie.js +2 -2
  20. package/lib/store/RelayExperimentalGraphResponseTransform.js +8 -8
  21. package/lib/store/RelayModernEnvironment.js +26 -19
  22. package/lib/store/RelayModernRecord.js +18 -8
  23. package/lib/store/RelayModernSelector.js +9 -9
  24. package/lib/store/RelayModernStore.js +152 -43
  25. package/lib/store/RelayPublishQueue.js +1 -1
  26. package/lib/store/RelayReader.js +76 -38
  27. package/lib/store/RelayRecordSource.js +6 -0
  28. package/lib/store/RelayReferenceMarker.js +2 -1
  29. package/lib/store/RelayResponseNormalizer.js +88 -55
  30. package/lib/store/RelayStoreSubscriptions.js +34 -10
  31. package/lib/store/RelayStoreUtils.js +8 -1
  32. package/lib/store/ResolverFragments.js +2 -2
  33. package/lib/store/live-resolvers/LiveResolverCache.js +25 -9
  34. package/lib/store/observeFragmentExperimental.js +17 -1
  35. package/lib/store/observeQueryExperimental.js +2 -2
  36. package/lib/subscription/requestSubscription.js +3 -3
  37. package/lib/util/RelayError.js +3 -0
  38. package/lib/util/RelayFeatureFlags.js +6 -2
  39. package/lib/util/RelayReplaySubject.js +4 -4
  40. package/lib/util/handlePotentialSnapshotErrors.js +2 -2
  41. package/lib/util/stableCopy.js +2 -2
  42. package/llm-docs/api-reference/entrypoint-apis/entrypoint-container.mdx +38 -0
  43. package/llm-docs/api-reference/entrypoint-apis/load-entrypoint.mdx +77 -0
  44. package/llm-docs/api-reference/entrypoint-apis/use-entrypoint-loader.mdx +99 -0
  45. package/llm-docs/api-reference/graphql/graphql-directives.mdx +378 -0
  46. package/llm-docs/api-reference/hooks/_use-lazy-load-query-extra.mdx +16 -0
  47. package/llm-docs/api-reference/hooks/load-query.mdx +84 -0
  48. package/llm-docs/api-reference/hooks/relay-environment-provider.mdx +78 -0
  49. package/llm-docs/api-reference/hooks/use-client-query.mdx +65 -0
  50. package/llm-docs/api-reference/hooks/use-fragment.mdx +69 -0
  51. package/llm-docs/api-reference/hooks/use-lazy-load-query.mdx +62 -0
  52. package/llm-docs/api-reference/hooks/use-mutation.mdx +94 -0
  53. package/llm-docs/api-reference/hooks/use-pagination-fragment.mdx +166 -0
  54. package/llm-docs/api-reference/hooks/use-prefetchable-forward-pagination-fragment.mdx +134 -0
  55. package/llm-docs/api-reference/hooks/use-preloaded-query.mdx +84 -0
  56. package/llm-docs/api-reference/hooks/use-query-loader.mdx +95 -0
  57. package/llm-docs/api-reference/hooks/use-refetchable-fragment.mdx +122 -0
  58. package/llm-docs/api-reference/hooks/use-relay-environment.mdx +37 -0
  59. package/llm-docs/api-reference/hooks/use-subscription.mdx +66 -0
  60. package/llm-docs/api-reference/relay-resolvers/docblock-format.mdx +321 -0
  61. package/llm-docs/api-reference/relay-resolvers/runtime-functions.mdx +94 -0
  62. package/llm-docs/api-reference/relay-runtime/commit-mutation.mdx +65 -0
  63. package/llm-docs/api-reference/relay-runtime/fetch-query.mdx +113 -0
  64. package/llm-docs/api-reference/relay-runtime/field-logger.mdx +170 -0
  65. package/llm-docs/api-reference/relay-runtime/observe-fragment.mdx +92 -0
  66. package/llm-docs/api-reference/relay-runtime/relay-environment.mdx +53 -0
  67. package/llm-docs/api-reference/relay-runtime/request-subscription.mdx +54 -0
  68. package/llm-docs/api-reference/relay-runtime/runtime-configuration.mdx +52 -0
  69. package/llm-docs/api-reference/relay-runtime/store.mdx +734 -0
  70. package/llm-docs/api-reference/relay-runtime/wait-for-fragment-data.mdx +89 -0
  71. package/llm-docs/api-reference/types/CacheConfig.mdx +8 -0
  72. package/llm-docs/api-reference/types/Disposable.mdx +4 -0
  73. package/llm-docs/api-reference/types/GraphQLSubscriptionConfig.mdx +17 -0
  74. package/llm-docs/api-reference/types/MutationConfig.mdx +31 -0
  75. package/llm-docs/api-reference/types/SelectorStoreUpdater.mdx +6 -0
  76. package/llm-docs/api-reference/types/UploadableMap.mdx +3 -0
  77. package/llm-docs/community/learning-resources.mdx +64 -0
  78. package/llm-docs/debugging/declarative-mutation-directives.mdx +34 -0
  79. package/llm-docs/debugging/disallowed-id-types-error.mdx +43 -0
  80. package/llm-docs/debugging/inconsistent-typename-error.mdx +47 -0
  81. package/llm-docs/debugging/relay-devtools.mdx +73 -0
  82. package/llm-docs/debugging/why-null.mdx +116 -0
  83. package/llm-docs/editor-support.mdx +55 -0
  84. package/llm-docs/error-reference/unknown-field.mdx +36 -0
  85. package/llm-docs/getting-started/babel-plugin.mdx +31 -0
  86. package/llm-docs/getting-started/compiler-config.mdx +25 -0
  87. package/llm-docs/getting-started/compiler.mdx +82 -0
  88. package/llm-docs/getting-started/lint-rules.mdx +87 -0
  89. package/llm-docs/getting-started/production.mdx +30 -0
  90. package/llm-docs/getting-started/quick-start.mdx +213 -0
  91. package/llm-docs/glossary/glossary.mdx +1040 -0
  92. package/llm-docs/guided-tour/list-data/advanced-pagination.mdx +157 -0
  93. package/llm-docs/guided-tour/list-data/connections.mdx +81 -0
  94. package/llm-docs/guided-tour/list-data/pagination.mdx +193 -0
  95. package/llm-docs/guided-tour/list-data/rendering-connections.mdx +112 -0
  96. package/llm-docs/guided-tour/list-data/streaming-pagination.mdx +87 -0
  97. package/llm-docs/guided-tour/managing-data-outside-react/retaining-queries.mdx +51 -0
  98. package/llm-docs/guided-tour/refetching/refetching-queries-with-different-data.mdx +337 -0
  99. package/llm-docs/guided-tour/refetching/refreshing-queries.mdx +350 -0
  100. package/llm-docs/guided-tour/rendering/environment.mdx +59 -0
  101. package/llm-docs/guided-tour/rendering/error-states.mdx +295 -0
  102. package/llm-docs/guided-tour/rendering/fragments.mdx +354 -0
  103. package/llm-docs/guided-tour/rendering/loading-states.mdx +245 -0
  104. package/llm-docs/guided-tour/rendering/queries.mdx +261 -0
  105. package/llm-docs/guided-tour/rendering/variables.mdx +233 -0
  106. package/llm-docs/guided-tour/reusing-cached-data/fetch-policies.mdx +56 -0
  107. package/llm-docs/guided-tour/reusing-cached-data/filling-in-missing-data.mdx +102 -0
  108. package/llm-docs/guided-tour/reusing-cached-data/introduction.mdx +22 -0
  109. package/llm-docs/guided-tour/reusing-cached-data/presence-of-data.mdx +93 -0
  110. package/llm-docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.mdx +175 -0
  111. package/llm-docs/guided-tour/reusing-cached-data/staleness-of-data.mdx +116 -0
  112. package/llm-docs/guided-tour/updating-data/client-only-data.mdx +115 -0
  113. package/llm-docs/guided-tour/updating-data/graphql-mutations.mdx +334 -0
  114. package/llm-docs/guided-tour/updating-data/graphql-subscriptions.mdx +279 -0
  115. package/llm-docs/guided-tour/updating-data/imperatively-modifying-linked-fields.mdx +511 -0
  116. package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data-legacy.mdx +142 -0
  117. package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data.mdx +275 -0
  118. package/llm-docs/guided-tour/updating-data/introduction.mdx +25 -0
  119. package/llm-docs/guided-tour/updating-data/local-data-updates.mdx +71 -0
  120. package/llm-docs/guided-tour/updating-data/typesafe-updaters-faq.mdx +83 -0
  121. package/llm-docs/guided-tour/updating-data/updating-connections.mdx +592 -0
  122. package/llm-docs/guides/alias-directive.mdx +160 -0
  123. package/llm-docs/guides/catch-directive.mdx +167 -0
  124. package/llm-docs/guides/client-schema-extensions.mdx +208 -0
  125. package/llm-docs/guides/codemods.mdx +66 -0
  126. package/llm-docs/guides/data-driven-dependencies/client-3d.mdx +255 -0
  127. package/llm-docs/guides/data-driven-dependencies/configuration.mdx +127 -0
  128. package/llm-docs/guides/data-driven-dependencies/introduction.mdx +39 -0
  129. package/llm-docs/guides/data-driven-dependencies/server-3d.mdx +664 -0
  130. package/llm-docs/guides/document-comparison.mdx +106 -0
  131. package/llm-docs/guides/graphql-server-specification.mdx +453 -0
  132. package/llm-docs/guides/network-layer.mdx +69 -0
  133. package/llm-docs/guides/persisted-queries.mdx +328 -0
  134. package/llm-docs/guides/relay-resolvers/context.mdx +99 -0
  135. package/llm-docs/guides/relay-resolvers/defining-fields.mdx +151 -0
  136. package/llm-docs/guides/relay-resolvers/defining-types.mdx +164 -0
  137. package/llm-docs/guides/relay-resolvers/deprecated.mdx +27 -0
  138. package/llm-docs/guides/relay-resolvers/derived-fields.mdx +127 -0
  139. package/llm-docs/guides/relay-resolvers/descriptions.mdx +44 -0
  140. package/llm-docs/guides/relay-resolvers/enabling.mdx +41 -0
  141. package/llm-docs/guides/relay-resolvers/errors.mdx +64 -0
  142. package/llm-docs/guides/relay-resolvers/field-arguments.mdx +63 -0
  143. package/llm-docs/guides/relay-resolvers/introduction.mdx +62 -0
  144. package/llm-docs/guides/relay-resolvers/limitations.mdx +30 -0
  145. package/llm-docs/guides/relay-resolvers/live-fields.mdx +164 -0
  146. package/llm-docs/guides/relay-resolvers/return-types.mdx +161 -0
  147. package/llm-docs/guides/relay-resolvers/suspense.mdx +41 -0
  148. package/llm-docs/guides/required-directive.mdx +240 -0
  149. package/llm-docs/guides/semantic-nullability.mdx +93 -0
  150. package/llm-docs/guides/testing-relay-components.mdx +642 -0
  151. package/llm-docs/guides/testing-relay-with-preloaded-queries.mdx +160 -0
  152. package/llm-docs/guides/throw-on-field-error-directive.mdx +58 -0
  153. package/llm-docs/guides/type-emission.mdx +414 -0
  154. package/llm-docs/home.mdx +32 -0
  155. package/llm-docs/principles-and-architecture/architecture-overview.mdx +24 -0
  156. package/llm-docs/principles-and-architecture/compiler-architecture.mdx +106 -0
  157. package/llm-docs/principles-and-architecture/runtime-architecture.mdx +249 -0
  158. package/llm-docs/principles-and-architecture/thinking-in-graphql.mdx +309 -0
  159. package/llm-docs/principles-and-architecture/thinking-in-relay.mdx +104 -0
  160. package/llm-docs/principles-and-architecture/videos.mdx +50 -0
  161. package/llm-docs/tutorial/arrays-lists.mdx +126 -0
  162. package/llm-docs/tutorial/fragments-1.mdx +487 -0
  163. package/llm-docs/tutorial/graphql.mdx +172 -0
  164. package/llm-docs/tutorial/interfaces-polymorphism.mdx +161 -0
  165. package/llm-docs/tutorial/intro.mdx +58 -0
  166. package/llm-docs/tutorial/mutations-updates.mdx +624 -0
  167. package/llm-docs/tutorial/organizing-mutations-queries-and-subscriptions.mdx +13 -0
  168. package/llm-docs/tutorial/queries-1.mdx +267 -0
  169. package/llm-docs/tutorial/queries-2.mdx +389 -0
  170. package/llm-docs/tutorial/refetchable-fragments.mdx +352 -0
  171. package/multi-actor-environment/ActorIdentifier.js.flow +2 -2
  172. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +7 -7
  173. package/multi-actor-environment/ActorUtils.js.flow +1 -1
  174. package/multi-actor-environment/MultiActorEnvironment.js.flow +12 -8
  175. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +3 -3
  176. package/mutations/RelayDeclarativeMutationConfig.js.flow +9 -9
  177. package/mutations/RelayRecordProxy.js.flow +8 -11
  178. package/mutations/RelayRecordSourceMutator.js.flow +4 -4
  179. package/mutations/RelayRecordSourceProxy.js.flow +4 -4
  180. package/mutations/RelayRecordSourceSelectorProxy.js.flow +6 -6
  181. package/mutations/applyOptimisticMutation.js.flow +2 -2
  182. package/mutations/commitMutation.js.flow +20 -16
  183. package/mutations/createUpdatableProxy.js.flow +19 -19
  184. package/mutations/readUpdatableFragment.js.flow +3 -3
  185. package/mutations/readUpdatableQuery.js.flow +3 -3
  186. package/mutations/validateMutation.js.flow +7 -7
  187. package/network/RelayNetworkTypes.js.flow +4 -4
  188. package/network/RelayObservable.js.flow +16 -14
  189. package/network/RelayQueryResponseCache.js.flow +3 -3
  190. package/network/wrapNetworkWithLogObserver.js.flow +1 -1
  191. package/package.json +2 -1
  192. package/query/GraphQLTag.js.flow +22 -10
  193. package/query/fetchQuery.js.flow +23 -10
  194. package/query/fetchQuery_DEPRECATED.js.flow +1 -1
  195. package/store/DataChecker.js.flow +43 -9
  196. package/store/NormalizationEngine.js.flow +779 -0
  197. package/store/OperationExecutor.js.flow +173 -70
  198. package/store/RelayConcreteVariables.js.flow +5 -5
  199. package/store/RelayErrorTrie.js.flow +12 -12
  200. package/store/RelayExperimentalGraphResponseHandler.js.flow +3 -3
  201. package/store/RelayExperimentalGraphResponseTransform.js.flow +10 -10
  202. package/store/RelayModernEnvironment.js.flow +41 -26
  203. package/store/RelayModernFragmentSpecResolver.js.flow +1 -1
  204. package/store/RelayModernOperationDescriptor.js.flow +1 -1
  205. package/store/RelayModernRecord.js.flow +44 -20
  206. package/store/RelayModernSelector.js.flow +21 -21
  207. package/store/RelayModernStore.js.flow +219 -58
  208. package/store/RelayOperationTracker.js.flow +2 -2
  209. package/store/RelayOptimisticRecordSource.js.flow +2 -2
  210. package/store/RelayPublishQueue.js.flow +21 -12
  211. package/store/RelayReader.js.flow +129 -57
  212. package/store/RelayRecordSource.js.flow +10 -0
  213. package/store/RelayRecordState.js.flow +1 -1
  214. package/store/RelayReferenceMarker.js.flow +5 -4
  215. package/store/RelayResponseNormalizer.js.flow +125 -57
  216. package/store/RelayStoreSubscriptions.js.flow +52 -8
  217. package/store/RelayStoreTypes.js.flow +153 -64
  218. package/store/RelayStoreUtils.js.flow +15 -7
  219. package/store/ResolverCache.js.flow +2 -2
  220. package/store/ResolverFragments.js.flow +12 -12
  221. package/store/StoreInspector.js.flow +6 -7
  222. package/store/cloneRelayHandleSourceField.js.flow +1 -1
  223. package/store/cloneRelayScalarHandleSourceField.js.flow +1 -1
  224. package/store/createRelayContext.js.flow +1 -1
  225. package/store/createRelayLoggingContext.js.flow +4 -4
  226. package/store/defaultGetDataID.js.flow +2 -2
  227. package/store/isRelayModernEnvironment.js.flow +4 -2
  228. package/store/live-resolvers/LiveResolverCache.js.flow +55 -20
  229. package/store/live-resolvers/LiveResolverSuspenseSentinel.js.flow +3 -3
  230. package/store/live-resolvers/getOutputTypeRecordIDs.js.flow +1 -1
  231. package/store/live-resolvers/isLiveStateValue.js.flow +2 -2
  232. package/store/live-resolvers/resolverDataInjector.js.flow +8 -5
  233. package/store/observeFragmentExperimental.js.flow +49 -20
  234. package/store/observeQueryExperimental.js.flow +5 -5
  235. package/store/readInlineData.js.flow +4 -4
  236. package/store/waitForFragmentExperimental.js.flow +3 -3
  237. package/subscription/requestSubscription.js.flow +7 -7
  238. package/util/NormalizationNode.js.flow +34 -32
  239. package/util/ReaderNode.js.flow +32 -30
  240. package/util/RelayConcreteNode.js.flow +5 -5
  241. package/util/RelayError.js.flow +4 -1
  242. package/util/RelayFeatureFlags.js.flow +21 -1
  243. package/util/RelayProfiler.js.flow +1 -1
  244. package/util/RelayReplaySubject.js.flow +3 -3
  245. package/util/RelayRuntimeTypes.js.flow +11 -11
  246. package/util/createPayloadFor3DField.js.flow +9 -5
  247. package/util/deepFreeze.js.flow +2 -2
  248. package/util/getFragmentIdentifier.js.flow +1 -1
  249. package/util/getPaginationMetadata.js.flow +1 -1
  250. package/util/getPaginationVariables.js.flow +1 -1
  251. package/util/getPendingOperationsForFragment.js.flow +2 -2
  252. package/util/getRefetchMetadata.js.flow +6 -5
  253. package/util/getValueAtPath.js.flow +3 -3
  254. package/util/handlePotentialSnapshotErrors.js.flow +5 -5
  255. package/util/isEmptyObject.js.flow +1 -1
  256. package/util/isPromise.js.flow +2 -2
  257. package/util/isScalarAndEqual.js.flow +1 -1
  258. package/util/recycleNodesInto.js.flow +2 -2
  259. package/util/registerEnvironmentWithDevTools.js.flow +1 -1
  260. package/util/shallowFreeze.js.flow +1 -1
  261. package/util/stableCopy.js.flow +5 -5
  262. package/util/withProvidedVariables.js.flow +14 -10
@@ -18,13 +18,13 @@ const SELF: Self = Symbol('$SELF');
18
18
 
19
19
  export opaque type Self = typeof SELF;
20
20
 
21
- export type TRelayFieldErrorForDisplay = $ReadOnly<{
22
- path?: $ReadOnlyArray<string | number>,
21
+ export type TRelayFieldErrorForDisplay = Readonly<{
22
+ path?: ReadonlyArray<string | number>,
23
23
  severity?: 'CRITICAL' | 'ERROR' | 'WARNING',
24
24
  }>;
25
25
 
26
26
  // We display a subset of the TRelayFieldError to the user. Removing the message by default.
27
- export type TRelayFieldError = $ReadOnly<{
27
+ export type TRelayFieldError = Readonly<{
28
28
  ...TRelayFieldErrorForDisplay,
29
29
  message: string,
30
30
  }>;
@@ -49,13 +49,13 @@ export opaque type RelayErrorTrie = Map<
49
49
  >;
50
50
 
51
51
  function buildErrorTrie(
52
- errors: ?$ReadOnlyArray<PayloadError>,
52
+ errors: ?ReadonlyArray<PayloadError>,
53
53
  ): RelayErrorTrie | null {
54
54
  if (errors == null) {
55
55
  return null;
56
56
  }
57
57
 
58
- const trie: $NonMaybeType<RelayErrorTrie> = new Map();
58
+ const trie: NonNullable<RelayErrorTrie> = new Map();
59
59
  // eslint-disable-next-line no-unused-vars
60
60
  ERRORS: for (const {path, locations: _, ...error} of errors) {
61
61
  if (path == null) {
@@ -100,7 +100,7 @@ function buildErrorTrie(
100
100
  function getErrorsByKey(
101
101
  trie: RelayErrorTrie,
102
102
  key: string | number,
103
- ): $ReadOnlyArray<TRelayFieldError> | null {
103
+ ): ReadonlyArray<TRelayFieldError> | null {
104
104
  const value = trie.get(key);
105
105
  if (value == null) {
106
106
  return null;
@@ -109,7 +109,7 @@ function getErrorsByKey(
109
109
  return value;
110
110
  }
111
111
  const errors: Array<
112
- $ReadOnly<{
112
+ Readonly<{
113
113
  message: string,
114
114
  path?: Array<string | number>,
115
115
  severity?: 'CRITICAL' | 'ERROR' | 'WARNING',
@@ -122,7 +122,7 @@ function getErrorsByKey(
122
122
  function recursivelyCopyErrorsIntoArray(
123
123
  trieOrSet: RelayErrorTrie,
124
124
  errors: Array<
125
- $ReadOnly<{
125
+ Readonly<{
126
126
  message: string,
127
127
  path?: Array<string | number>,
128
128
  severity?: 'CRITICAL' | 'ERROR' | 'WARNING',
@@ -165,14 +165,14 @@ function getNestedErrorTrieByKey(
165
165
  return null;
166
166
  }
167
167
 
168
- module.exports = ({
168
+ module.exports = {
169
169
  SELF,
170
170
  buildErrorTrie,
171
- getNestedErrorTrieByKey,
172
171
  getErrorsByKey,
173
- }: {
172
+ getNestedErrorTrieByKey,
173
+ } as {
174
174
  SELF: typeof SELF,
175
175
  buildErrorTrie: typeof buildErrorTrie,
176
176
  getNestedErrorTrieByKey: typeof getNestedErrorTrieByKey,
177
177
  getErrorsByKey: typeof getErrorsByKey,
178
- });
178
+ };
@@ -58,7 +58,7 @@ class GraphModeHandler {
58
58
  this._streamIdToCacheKey.clear();
59
59
  break;
60
60
  default:
61
- (chunk.$kind: empty);
61
+ chunk.$kind as empty;
62
62
  }
63
63
  }
64
64
  return this._recordSource;
@@ -93,12 +93,12 @@ class GraphModeHandler {
93
93
  } else {
94
94
  if (value.hasOwnProperty('__id')) {
95
95
  // Singular
96
- const streamID: number = (value.__id: any);
96
+ const streamID: number = value.__id as any;
97
97
  const id = this._lookupCacheKey(streamID);
98
98
  RelayModernRecord.setLinkedRecordID(parentRecord, key, id);
99
99
  } else if (value.hasOwnProperty('__ids')) {
100
100
  // Plural
101
- const streamIDs: Array<number | null> = (value.__ids: any);
101
+ const streamIDs: Array<number | null> = value.__ids as any;
102
102
  const ids = streamIDs.map((sID): ?DataID => {
103
103
  return sID == null ? null : this._lookupCacheKey(sID);
104
104
  });
@@ -183,7 +183,7 @@ export class GraphModeNormalizer {
183
183
  }
184
184
 
185
185
  _getObjectType(data: PayloadData): string {
186
- const typeName = (data: any)[TYPENAME_KEY];
186
+ const typeName = (data as any)[TYPENAME_KEY];
187
187
  invariant(
188
188
  typeName != null,
189
189
  'Expected a typename for record `%s`.',
@@ -198,7 +198,7 @@ export class GraphModeNormalizer {
198
198
  return getStorageKey(selection, this._variables);
199
199
  }
200
200
 
201
- _getVariableValue(name: string): mixed {
201
+ _getVariableValue(name: string): unknown {
202
202
  invariant(
203
203
  this._variables.hasOwnProperty(name),
204
204
  'Unexpected undefined variable `%s`.',
@@ -218,10 +218,10 @@ export class GraphModeNormalizer {
218
218
  const $streamID = this._getStreamID();
219
219
  yield {
220
220
  ...rootFields,
221
- $kind: 'Record',
222
- $streamID,
223
221
  __id: dataID,
224
222
  __typename: ROOT_TYPE,
223
+ $kind: 'Record',
224
+ $streamID,
225
225
  } as RecordChunk;
226
226
  yield {
227
227
  $kind: 'Complete',
@@ -243,9 +243,9 @@ export class GraphModeNormalizer {
243
243
  // experimental transform
244
244
  yield {
245
245
  ...fields,
246
- $kind: 'Record',
247
- __typename: typename,
248
246
  __id: cacheKey,
247
+ __typename: typename,
248
+ $kind: 'Record',
249
249
  $streamID,
250
250
  } as RecordChunk;
251
251
  } else if (Object.keys(fields).length > 0) {
@@ -267,7 +267,7 @@ export class GraphModeNormalizer {
267
267
  switch (selection.kind) {
268
268
  case LINKED_FIELD: {
269
269
  const responseKey = selection.alias ?? selection.name;
270
- const fieldData: PayloadData = (data[responseKey]: any);
270
+ const fieldData: PayloadData = data[responseKey] as any;
271
271
 
272
272
  const storageKey = this._getStorageKey(selection);
273
273
 
@@ -305,7 +305,7 @@ export class GraphModeNormalizer {
305
305
  this.duplicateFieldsAvoided++;
306
306
  break;
307
307
  }
308
- const fieldData: ChunkField = (data[responseKey]: any);
308
+ const fieldData: ChunkField = data[responseKey] as any;
309
309
 
310
310
  parentFields[storageKey] = fieldData;
311
311
  sentFields.add(storageKey);
@@ -378,8 +378,9 @@ export class GraphModeNormalizer {
378
378
  // Otherwise data *for this selection* should not be present: enqueue
379
379
  // metadata to process the subsequent response chunk.
380
380
  this._incrementalPlaceholders.push({
381
- kind: 'defer',
381
+ actorIdentifier: this._actorIdentifier,
382
382
  data,
383
+ kind: 'defer',
383
384
  label: selection.label,
384
385
  path: [...this._path],
385
386
  selector: createNormalizationSelector(
@@ -388,7 +389,6 @@ export class GraphModeNormalizer {
388
389
  this._variables,
389
390
  ),
390
391
  typeName: this._getObjectType(data),
391
- actorIdentifier: this._actorIdentifier,
392
392
  });
393
393
  }
394
394
  break;
@@ -67,17 +67,18 @@ export type EnvironmentConfig = {
67
67
  +configName?: string,
68
68
  +handlerProvider?: ?HandlerProvider,
69
69
  +treatMissingFieldsAsNull?: boolean,
70
+ +deferDeduplicatedFields?: boolean,
70
71
  +log?: ?LogFunction,
71
72
  +operationLoader?: ?OperationLoader,
72
73
  +network: INetwork,
73
74
  +normalizeResponse?: ?NormalizeResponseFunction,
74
75
  +scheduler?: ?TaskScheduler,
75
76
  +store?: Store,
76
- +missingFieldHandlers?: ?$ReadOnlyArray<MissingFieldHandler>,
77
+ +missingFieldHandlers?: ?ReadonlyArray<MissingFieldHandler>,
77
78
  +operationTracker?: ?OperationTracker,
78
79
  +getDataID?: ?GetDataID,
79
80
  +UNSTABLE_defaultRenderPolicy?: ?RenderPolicy,
80
- +options?: mixed,
81
+ +options?: unknown,
81
82
  +isServer?: boolean,
82
83
  +relayFieldLogger?: ?RelayFieldLogger,
83
84
  +shouldProcessClientComponents?: ?boolean,
@@ -93,12 +94,13 @@ class RelayModernEnvironment implements IEnvironment {
93
94
  _scheduler: ?TaskScheduler;
94
95
  _store: Store;
95
96
  configName: ?string;
96
- _missingFieldHandlers: $ReadOnlyArray<MissingFieldHandler>;
97
+ _missingFieldHandlers: ReadonlyArray<MissingFieldHandler>;
97
98
  _operationTracker: OperationTracker;
98
99
  _getDataID: GetDataID;
99
100
  _treatMissingFieldsAsNull: boolean;
101
+ _deferDeduplicatedFields: boolean;
100
102
  _operationExecutions: Map<string, ActiveState>;
101
- +options: mixed;
103
+ +options: unknown;
102
104
  +_isServer: boolean;
103
105
  relayFieldLogger: RelayFieldLogger;
104
106
  _normalizeResponse: NormalizeResponseFunction;
@@ -106,6 +108,7 @@ class RelayModernEnvironment implements IEnvironment {
106
108
  constructor(config: EnvironmentConfig) {
107
109
  this.configName = config.configName;
108
110
  this._treatMissingFieldsAsNull = config.treatMissingFieldsAsNull === true;
111
+ this._deferDeduplicatedFields = config.deferDeduplicatedFields === true;
109
112
  const operationLoader = config.operationLoader;
110
113
  if (__DEV__) {
111
114
  if (operationLoader != null) {
@@ -122,9 +125,9 @@ class RelayModernEnvironment implements IEnvironment {
122
125
  const store =
123
126
  config.store ??
124
127
  new RelayModernStore(new RelayRecordSource(), {
128
+ getDataID: config.getDataID,
125
129
  log: config.log,
126
130
  operationLoader: config.operationLoader,
127
- getDataID: config.getDataID,
128
131
  shouldProcessClientComponents: config.shouldProcessClientComponents,
129
132
  });
130
133
 
@@ -150,12 +153,12 @@ class RelayModernEnvironment implements IEnvironment {
150
153
  this._isServer = config.isServer ?? false;
151
154
  this._normalizeResponse = config.normalizeResponse ?? normalizeResponse;
152
155
 
153
- (this: any).__setNet = newNet =>
156
+ (this as any).__setNet = newNet =>
154
157
  (this._network = wrapNetworkWithLogObserver(this, newNet));
155
158
 
156
159
  if (__DEV__) {
157
160
  const {inspect} = require('./StoreInspector');
158
- (this: any).DEBUG_inspect = (dataID: ?string) => inspect(this, dataID);
161
+ (this as any).DEBUG_inspect = (dataID: ?string) => inspect(this, dataID);
159
162
  }
160
163
 
161
164
  this._operationTracker =
@@ -224,7 +227,7 @@ class RelayModernEnvironment implements IEnvironment {
224
227
  });
225
228
  }
226
229
 
227
- applyMutation<TMutation: MutationParameters>(
230
+ applyMutation<TMutation extends MutationParameters>(
228
231
  optimisticConfig: OptimisticResponseConfig<TMutation>,
229
232
  ): Disposable {
230
233
  const subscription = this._execute({
@@ -256,7 +259,7 @@ class RelayModernEnvironment implements IEnvironment {
256
259
  this._execute({
257
260
  createSource: () => RelayObservable.from({data: payload}),
258
261
  isClientPayload: true,
259
- operation: operation,
262
+ operation,
260
263
  optimisticConfig: null,
261
264
  updater: null,
262
265
  }).subscribe({});
@@ -284,18 +287,28 @@ class RelayModernEnvironment implements IEnvironment {
284
287
  return this._store.retain(operation);
285
288
  }
286
289
 
290
+ experimental_batchUpdates(callback: () => void): void {
291
+ // $FlowFixMe[prop-missing] - experimental method not on Store interface
292
+ const batchFn = this._store.experimental_batchUpdates;
293
+ invariant(
294
+ typeof batchFn === 'function',
295
+ 'RelayModernEnvironment: The current store does not support experimental_batchUpdates.',
296
+ );
297
+ // We must use .call to preserve Flow's narrowing from the above typeof check.
298
+ batchFn.call(this._store, callback);
299
+ }
300
+
287
301
  isServer(): boolean {
288
302
  return this._isServer;
289
303
  }
290
304
 
291
305
  _checkSelectorAndHandleMissingFields(
292
306
  operation: OperationDescriptor,
293
- handlers: $ReadOnlyArray<MissingFieldHandler>,
307
+ handlers: ReadonlyArray<MissingFieldHandler>,
294
308
  ): OperationAvailability {
295
309
  const target = RelayRecordSource.create();
296
310
  const source = this._store.getSource();
297
311
  const result = this._store.check(operation, {
298
- handlers,
299
312
  defaultActorIdentifier: INTERNAL_ACTOR_IDENTIFIER_DO_NOT_USE,
300
313
  getSourceForActor(actorIdentifier: ActorIdentifier) {
301
314
  assertInternalActorIdentifier(actorIdentifier);
@@ -305,6 +318,7 @@ class RelayModernEnvironment implements IEnvironment {
305
318
  assertInternalActorIdentifier(actorIdentifier);
306
319
  return target;
307
320
  },
321
+ handlers,
308
322
  });
309
323
  if (target.size() > 0) {
310
324
  this._scheduleUpdates(() => {
@@ -365,7 +379,7 @@ class RelayModernEnvironment implements IEnvironment {
365
379
  * Note: Observables are lazy, so calling this method will do nothing until
366
380
  * the result is subscribed to: environment.execute({...}).subscribe({...}).
367
381
  */
368
- executeSubscription<TMutation: MutationParameters>({
382
+ executeSubscription<TMutation extends MutationParameters>({
369
383
  operation,
370
384
  updater,
371
385
  }: {
@@ -397,7 +411,7 @@ class RelayModernEnvironment implements IEnvironment {
397
411
  * the result is subscribed to:
398
412
  * environment.executeMutation({...}).subscribe({...}).
399
413
  */
400
- executeMutation<TMutation: MutationParameters>({
414
+ executeMutation<TMutation extends MutationParameters>({
401
415
  operation,
402
416
  optimisticResponse,
403
417
  optimisticUpdater,
@@ -407,7 +421,7 @@ class RelayModernEnvironment implements IEnvironment {
407
421
  let optimisticConfig;
408
422
  if (optimisticResponse || optimisticUpdater) {
409
423
  optimisticConfig = {
410
- operation: operation,
424
+ operation,
411
425
  response: optimisticResponse,
412
426
  updater: optimisticUpdater,
413
427
  };
@@ -455,11 +469,11 @@ class RelayModernEnvironment implements IEnvironment {
455
469
  });
456
470
  }
457
471
 
458
- toJSON(): mixed {
472
+ toJSON(): unknown {
459
473
  return `RelayModernEnvironment(${this.configName ?? ''})`;
460
474
  }
461
475
 
462
- _execute<TMutation: MutationParameters>({
476
+ _execute<TMutation extends MutationParameters>({
463
477
  createSource,
464
478
  isClientPayload,
465
479
  operation,
@@ -478,30 +492,31 @@ class RelayModernEnvironment implements IEnvironment {
478
492
  const executor = OperationExecutor.execute<$FlowFixMe>({
479
493
  actorIdentifier: INTERNAL_ACTOR_IDENTIFIER_DO_NOT_USE,
480
494
  getDataID: this._getDataID,
495
+ getPublishQueue(actorIdentifier: ActorIdentifier) {
496
+ assertInternalActorIdentifier(actorIdentifier);
497
+ return publishQueue;
498
+ },
499
+ getStore(actorIdentifier: ActorIdentifier) {
500
+ assertInternalActorIdentifier(actorIdentifier);
501
+ return store;
502
+ },
481
503
  isClientPayload,
482
504
  log: this.__log,
505
+ normalizeResponse: this._normalizeResponse,
483
506
  operation,
484
507
  operationExecutions: this._operationExecutions,
485
508
  operationLoader: this._operationLoader,
486
509
  operationTracker: this._operationTracker,
487
510
  optimisticConfig,
488
- getPublishQueue(actorIdentifier: ActorIdentifier) {
489
- assertInternalActorIdentifier(actorIdentifier);
490
- return publishQueue;
491
- },
492
511
  scheduler: this._scheduler,
493
512
  shouldProcessClientComponents: this._shouldProcessClientComponents,
494
513
  sink,
495
514
  // NOTE: Some product tests expect `Network.execute` to be called only
496
515
  // when the Observable is executed.
497
516
  source: createSource(),
498
- getStore(actorIdentifier: ActorIdentifier) {
499
- assertInternalActorIdentifier(actorIdentifier);
500
- return store;
501
- },
502
517
  treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
518
+ deferDeduplicatedFields: this._deferDeduplicatedFields,
503
519
  updater,
504
- normalizeResponse: this._normalizeResponse,
505
520
  });
506
521
  return () => executor.cancel();
507
522
  });
@@ -520,7 +535,7 @@ function operationHasClientAbstractTypes(
520
535
  // Add a sigil for detection by `isRelayModernEnvironment()` to avoid a
521
536
  // realm-specific instanceof check, and to aid in module tree-shaking to
522
537
  // avoid requiring all of RelayRuntime just to detect its environment.
523
- (RelayModernEnvironment: any).prototype['@@RelayModernEnvironment'] = true;
538
+ (RelayModernEnvironment as any).prototype['@@RelayModernEnvironment'] = true;
524
539
 
525
540
  function emptyFunction() {}
526
541
 
@@ -43,7 +43,7 @@ const areEqual = require('areEqual');
43
43
  const invariant = require('invariant');
44
44
  const warning = require('warning');
45
45
 
46
- type Props = {[key: string]: mixed, ...};
46
+ type Props = {[key: string]: unknown, ...};
47
47
  type Resolvers = {
48
48
  [key: string]: ?(SelectorListResolver | SelectorResolver),
49
49
  ...
@@ -39,7 +39,7 @@ const invariant = require('invariant');
39
39
  * are filtered to exclude variables that do not match defined arguments on the
40
40
  * operation, and default values are populated for null values.
41
41
  */
42
- function createOperationDescriptor<TQuery: OperationType>(
42
+ function createOperationDescriptor<TQuery extends OperationType>(
43
43
  request: ConcreteRequest,
44
44
  variables: VariablesOf<TQuery>,
45
45
  cacheConfig?: ?CacheConfig,
@@ -37,7 +37,7 @@ const warning = require('warning');
37
37
 
38
38
  export type StorageKey = Exclude<string, typeof ERRORS_KEY>;
39
39
 
40
- type RelayFieldErrors = {[StorageKey]: $ReadOnlyArray<TRelayFieldError>};
40
+ type RelayFieldErrors = {[StorageKey]: ReadonlyArray<TRelayFieldError>};
41
41
 
42
42
  export type RecordJSON = {
43
43
  /**
@@ -45,7 +45,7 @@ export type RecordJSON = {
45
45
  * not support types with multiple indexers.
46
46
  */
47
47
  __errors?: RelayFieldErrors,
48
- [StorageKey]: mixed,
48
+ [StorageKey]: unknown,
49
49
  ...
50
50
  };
51
51
 
@@ -147,7 +147,7 @@ function create(dataID: DataID, typeName: string): Record {
147
147
  *
148
148
  * Convert the JSON representation of a record into a record.
149
149
  */
150
- function fromObject<TMaybe: ?empty = empty>(
150
+ function fromObject<TMaybe extends ?empty = empty>(
151
151
  json: RecordJSON | TMaybe,
152
152
  ): Record | TMaybe {
153
153
  return json;
@@ -159,7 +159,7 @@ function fromObject<TMaybe: ?empty = empty>(
159
159
  * Get the record's `id` if available or the client-generated identifier.
160
160
  */
161
161
  function getDataID(record: Record): DataID {
162
- return (record[ID_KEY]: any);
162
+ return record[ID_KEY] as any;
163
163
  }
164
164
 
165
165
  /**
@@ -180,7 +180,7 @@ function getFields(record: Record): Array<StorageKey> {
180
180
  * Get the concrete type of the record.
181
181
  */
182
182
  function getType(record: Record): string {
183
- return (record[TYPENAME_KEY]: any);
183
+ return record[TYPENAME_KEY] as any;
184
184
  }
185
185
 
186
186
  /**
@@ -191,7 +191,7 @@ function getType(record: Record): string {
191
191
  function getErrors(
192
192
  record: Record,
193
193
  storageKey: StorageKey,
194
- ): $ReadOnlyArray<TRelayFieldError> | void {
194
+ ): ReadonlyArray<TRelayFieldError> | void {
195
195
  return record[ERRORS_KEY]?.[storageKey];
196
196
  }
197
197
 
@@ -200,7 +200,7 @@ function getErrors(
200
200
  *
201
201
  * Get a scalar (non-link) field value.
202
202
  */
203
- function getValue(record: Record, storageKey: StorageKey): mixed {
203
+ function getValue(record: Record, storageKey: StorageKey): unknown {
204
204
  const value = record[storageKey];
205
205
  if (value && typeof value === 'object') {
206
206
  invariant(
@@ -252,7 +252,7 @@ function getLinkedRecordID(record: Record, storageKey: StorageKey): ?DataID {
252
252
  'getLinkedRecords() instead of getLinkedRecord()?'
253
253
  : '',
254
254
  );
255
- // $FlowFixMe[incompatible-return]
255
+ // $FlowFixMe[incompatible-type]
256
256
  return link[REF_KEY];
257
257
  }
258
258
 
@@ -297,7 +297,7 @@ function getLinkedRecordIDs(
297
297
  : '',
298
298
  );
299
299
  // assume items of the array are ids
300
- return (links[REFS_KEY]: any);
300
+ return links[REFS_KEY] as any;
301
301
  }
302
302
 
303
303
  /**
@@ -488,7 +488,7 @@ function freeze(record: Record): void {
488
488
  function setErrors(
489
489
  record: Record,
490
490
  storageKey: StorageKey,
491
- errors?: $ReadOnlyArray<TRelayFieldError>,
491
+ errors?: ReadonlyArray<TRelayFieldError>,
492
492
  ): void {
493
493
  if (__DEV__) {
494
494
  warning(
@@ -523,7 +523,11 @@ function setErrors(
523
523
  *
524
524
  * Set the value of a storageKey to a scalar.
525
525
  */
526
- function setValue(record: Record, storageKey: StorageKey, value: mixed): void {
526
+ function setValue(
527
+ record: Record,
528
+ storageKey: StorageKey,
529
+ value: unknown,
530
+ ): void {
527
531
  if (__DEV__) {
528
532
  const prevID = getDataID(record);
529
533
  if (storageKey === ID_KEY) {
@@ -629,7 +633,7 @@ function getActorLinkedRecordID(
629
633
  JSON.stringify(link),
630
634
  );
631
635
 
632
- return [(link[ACTOR_IDENTIFIER_KEY]: any), (link[REF_KEY]: any)];
636
+ return [link[ACTOR_IDENTIFIER_KEY] as any, link[REF_KEY] as any];
633
637
  }
634
638
 
635
639
  function getResolverLinkedRecordID(record: Record, typeName: string): ?DataID {
@@ -682,12 +686,31 @@ function getResolverLinkedRecordIDs(
682
686
  });
683
687
  }
684
688
 
689
+ /**
690
+ * @public
691
+ *
692
+ * Returns true if the value of a field differs between two records.
693
+ * Unlike getValue(), this works for all field types (scalar, linked, plural linked).
694
+ */
695
+ function hasFieldChanged(
696
+ prevRecord: Record,
697
+ nextRecord: Record,
698
+ storageKey: StorageKey,
699
+ ): boolean {
700
+ if (!areEqual(prevRecord[storageKey], nextRecord[storageKey])) {
701
+ return true;
702
+ }
703
+ const prevErrors = prevRecord[ERRORS_KEY]?.[storageKey];
704
+ const nextErrors = nextRecord[ERRORS_KEY]?.[storageKey];
705
+ return !areEqual(prevErrors, nextErrors);
706
+ }
707
+
685
708
  /**
686
709
  * @public
687
710
  *
688
711
  * Convert a record to JSON.
689
712
  */
690
- function toJSON<TMaybe: ?empty = empty>(
713
+ function toJSON<TMaybe extends ?empty = empty>(
691
714
  record: Record | TMaybe,
692
715
  ): RecordJSON | TMaybe {
693
716
  return record;
@@ -699,26 +722,27 @@ module.exports = {
699
722
  create,
700
723
  freeze,
701
724
  fromObject,
725
+ getActorLinkedRecordID,
702
726
  getDataID,
703
727
  getErrors,
704
728
  getFields,
705
729
  getInvalidationEpoch,
706
730
  getLinkedRecordID,
707
731
  getLinkedRecordIDs,
732
+ getResolverLinkedRecordID,
733
+ getResolverLinkedRecordIDs,
708
734
  getType,
709
735
  getValue,
710
- hasValue,
736
+ hasFieldChanged,
711
737
  hasLinkedRecordID,
712
738
  hasLinkedRecordIDs,
739
+ hasValue,
713
740
  merge,
741
+ setActorLinkedRecordID,
714
742
  setErrors,
715
- setValue,
716
743
  setLinkedRecordID,
717
744
  setLinkedRecordIDs,
718
- update,
719
- getActorLinkedRecordID,
720
- setActorLinkedRecordID,
721
- getResolverLinkedRecordID,
722
- getResolverLinkedRecordIDs,
745
+ setValue,
723
746
  toJSON,
747
+ update,
724
748
  };