relay-runtime 20.1.1 → 21.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/experimental.d.ts +34 -0
  2. package/experimental.js +1 -1
  3. package/experimental.js.flow +11 -11
  4. package/handlers/RelayDefaultHandlerProvider.d.ts +12 -0
  5. package/handlers/connection/ConnectionHandler.d.ts +51 -0
  6. package/handlers/connection/ConnectionHandler.js.flow +5 -5
  7. package/handlers/connection/ConnectionInterface.d.ts +40 -0
  8. package/handlers/connection/ConnectionInterface.js.flow +1 -1
  9. package/handlers/connection/MutationHandlers.d.ts +17 -0
  10. package/index.d.ts +274 -0
  11. package/index.js +1 -1
  12. package/index.js.flow +125 -62
  13. package/lib/experimental.js +3 -3
  14. package/lib/index.js +105 -57
  15. package/lib/multi-actor-environment/ActorIdentifier.js +2 -2
  16. package/lib/multi-actor-environment/MultiActorEnvironment.js +3 -1
  17. package/lib/mutations/commitMutation.js +8 -8
  18. package/lib/mutations/validateMutation.js +4 -4
  19. package/lib/query/GraphQLTag.js +3 -3
  20. package/lib/query/fetchQuery.js +15 -3
  21. package/lib/store/DataChecker.js +38 -4
  22. package/lib/store/NormalizationEngine.js +373 -0
  23. package/lib/store/OperationExecutor.js +172 -113
  24. package/lib/store/RelayConcreteVariables.js +1 -1
  25. package/lib/store/RelayErrorTrie.js +2 -2
  26. package/lib/store/RelayExperimentalGraphResponseTransform.js +8 -8
  27. package/lib/store/RelayModernEnvironment.js +26 -19
  28. package/lib/store/RelayModernRecord.js +18 -8
  29. package/lib/store/RelayModernSelector.js +9 -9
  30. package/lib/store/RelayModernStore.js +152 -43
  31. package/lib/store/RelayPublishQueue.js +1 -1
  32. package/lib/store/RelayReader.js +76 -38
  33. package/lib/store/RelayRecordSource.js +6 -0
  34. package/lib/store/RelayReferenceMarker.js +2 -1
  35. package/lib/store/RelayResponseNormalizer.js +88 -55
  36. package/lib/store/RelayStoreSubscriptions.js +34 -10
  37. package/lib/store/RelayStoreUtils.js +8 -1
  38. package/lib/store/ResolverFragments.js +2 -2
  39. package/lib/store/live-resolvers/LiveResolverCache.js +25 -9
  40. package/lib/store/observeFragmentExperimental.js +17 -1
  41. package/lib/store/observeQueryExperimental.js +2 -2
  42. package/lib/subscription/requestSubscription.js +3 -3
  43. package/lib/util/RelayError.js +3 -0
  44. package/lib/util/RelayFeatureFlags.js +6 -2
  45. package/lib/util/RelayReplaySubject.js +4 -4
  46. package/lib/util/handlePotentialSnapshotErrors.js +2 -2
  47. package/lib/util/stableCopy.js +2 -2
  48. package/llm-docs/api-reference/entrypoint-apis/entrypoint-container.mdx +38 -0
  49. package/llm-docs/api-reference/entrypoint-apis/load-entrypoint.mdx +77 -0
  50. package/llm-docs/api-reference/entrypoint-apis/use-entrypoint-loader.mdx +99 -0
  51. package/llm-docs/api-reference/graphql/graphql-directives.mdx +378 -0
  52. package/llm-docs/api-reference/hooks/_use-lazy-load-query-extra.mdx +16 -0
  53. package/llm-docs/api-reference/hooks/load-query.mdx +84 -0
  54. package/llm-docs/api-reference/hooks/relay-environment-provider.mdx +78 -0
  55. package/llm-docs/api-reference/hooks/use-client-query.mdx +65 -0
  56. package/llm-docs/api-reference/hooks/use-fragment.mdx +69 -0
  57. package/llm-docs/api-reference/hooks/use-lazy-load-query.mdx +62 -0
  58. package/llm-docs/api-reference/hooks/use-mutation.mdx +94 -0
  59. package/llm-docs/api-reference/hooks/use-pagination-fragment.mdx +166 -0
  60. package/llm-docs/api-reference/hooks/use-prefetchable-forward-pagination-fragment.mdx +134 -0
  61. package/llm-docs/api-reference/hooks/use-preloaded-query.mdx +84 -0
  62. package/llm-docs/api-reference/hooks/use-query-loader.mdx +95 -0
  63. package/llm-docs/api-reference/hooks/use-refetchable-fragment.mdx +122 -0
  64. package/llm-docs/api-reference/hooks/use-relay-environment.mdx +37 -0
  65. package/llm-docs/api-reference/hooks/use-subscription.mdx +66 -0
  66. package/llm-docs/api-reference/relay-resolvers/docblock-format.mdx +321 -0
  67. package/llm-docs/api-reference/relay-resolvers/runtime-functions.mdx +94 -0
  68. package/llm-docs/api-reference/relay-runtime/commit-mutation.mdx +65 -0
  69. package/llm-docs/api-reference/relay-runtime/fetch-query.mdx +118 -0
  70. package/llm-docs/api-reference/relay-runtime/field-logger.mdx +170 -0
  71. package/llm-docs/api-reference/relay-runtime/observe-fragment.mdx +92 -0
  72. package/llm-docs/api-reference/relay-runtime/relay-environment.mdx +53 -0
  73. package/llm-docs/api-reference/relay-runtime/request-subscription.mdx +54 -0
  74. package/llm-docs/api-reference/relay-runtime/runtime-configuration.mdx +52 -0
  75. package/llm-docs/api-reference/relay-runtime/store.mdx +734 -0
  76. package/llm-docs/api-reference/relay-runtime/wait-for-fragment-data.mdx +89 -0
  77. package/llm-docs/api-reference/types/CacheConfig.mdx +8 -0
  78. package/llm-docs/api-reference/types/Disposable.mdx +4 -0
  79. package/llm-docs/api-reference/types/GraphQLSubscriptionConfig.mdx +17 -0
  80. package/llm-docs/api-reference/types/MutationConfig.mdx +31 -0
  81. package/llm-docs/api-reference/types/SelectorStoreUpdater.mdx +6 -0
  82. package/llm-docs/api-reference/types/UploadableMap.mdx +3 -0
  83. package/llm-docs/community/learning-resources.mdx +64 -0
  84. package/llm-docs/debugging/declarative-mutation-directives.mdx +34 -0
  85. package/llm-docs/debugging/disallowed-id-types-error.mdx +43 -0
  86. package/llm-docs/debugging/inconsistent-typename-error.mdx +47 -0
  87. package/llm-docs/debugging/relay-devtools.mdx +73 -0
  88. package/llm-docs/debugging/why-null.mdx +116 -0
  89. package/llm-docs/editor-support.mdx +55 -0
  90. package/llm-docs/error-reference/unknown-field.mdx +36 -0
  91. package/llm-docs/getting-started/babel-plugin.mdx +31 -0
  92. package/llm-docs/getting-started/compiler-config.mdx +25 -0
  93. package/llm-docs/getting-started/compiler.mdx +98 -0
  94. package/llm-docs/getting-started/lint-rules.mdx +87 -0
  95. package/llm-docs/getting-started/production.mdx +30 -0
  96. package/llm-docs/getting-started/quick-start.mdx +216 -0
  97. package/llm-docs/glossary/glossary.mdx +1040 -0
  98. package/llm-docs/guided-tour/list-data/advanced-pagination.mdx +157 -0
  99. package/llm-docs/guided-tour/list-data/connections.mdx +81 -0
  100. package/llm-docs/guided-tour/list-data/pagination.mdx +193 -0
  101. package/llm-docs/guided-tour/list-data/rendering-connections.mdx +112 -0
  102. package/llm-docs/guided-tour/list-data/streaming-pagination.mdx +87 -0
  103. package/llm-docs/guided-tour/managing-data-outside-react/retaining-queries.mdx +51 -0
  104. package/llm-docs/guided-tour/refetching/refetching-queries-with-different-data.mdx +337 -0
  105. package/llm-docs/guided-tour/refetching/refreshing-queries.mdx +350 -0
  106. package/llm-docs/guided-tour/rendering/environment.mdx +59 -0
  107. package/llm-docs/guided-tour/rendering/error-states.mdx +295 -0
  108. package/llm-docs/guided-tour/rendering/fragments.mdx +354 -0
  109. package/llm-docs/guided-tour/rendering/loading-states.mdx +245 -0
  110. package/llm-docs/guided-tour/rendering/queries.mdx +261 -0
  111. package/llm-docs/guided-tour/rendering/variables.mdx +233 -0
  112. package/llm-docs/guided-tour/reusing-cached-data/fetch-policies.mdx +56 -0
  113. package/llm-docs/guided-tour/reusing-cached-data/filling-in-missing-data.mdx +102 -0
  114. package/llm-docs/guided-tour/reusing-cached-data/introduction.mdx +22 -0
  115. package/llm-docs/guided-tour/reusing-cached-data/presence-of-data.mdx +93 -0
  116. package/llm-docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.mdx +175 -0
  117. package/llm-docs/guided-tour/reusing-cached-data/staleness-of-data.mdx +116 -0
  118. package/llm-docs/guided-tour/updating-data/client-only-data.mdx +115 -0
  119. package/llm-docs/guided-tour/updating-data/graphql-mutations.mdx +334 -0
  120. package/llm-docs/guided-tour/updating-data/graphql-subscriptions.mdx +279 -0
  121. package/llm-docs/guided-tour/updating-data/imperatively-modifying-linked-fields.mdx +511 -0
  122. package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data-legacy.mdx +142 -0
  123. package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data.mdx +275 -0
  124. package/llm-docs/guided-tour/updating-data/introduction.mdx +25 -0
  125. package/llm-docs/guided-tour/updating-data/local-data-updates.mdx +71 -0
  126. package/llm-docs/guided-tour/updating-data/typesafe-updaters-faq.mdx +83 -0
  127. package/llm-docs/guided-tour/updating-data/updating-connections.mdx +592 -0
  128. package/llm-docs/guides/alias-directive.mdx +160 -0
  129. package/llm-docs/guides/catch-directive.mdx +167 -0
  130. package/llm-docs/guides/client-schema-extensions.mdx +208 -0
  131. package/llm-docs/guides/codemods.mdx +79 -0
  132. package/llm-docs/guides/data-driven-dependencies/client-3d.mdx +255 -0
  133. package/llm-docs/guides/data-driven-dependencies/configuration.mdx +127 -0
  134. package/llm-docs/guides/data-driven-dependencies/introduction.mdx +39 -0
  135. package/llm-docs/guides/data-driven-dependencies/server-3d.mdx +664 -0
  136. package/llm-docs/guides/document-comparison.mdx +106 -0
  137. package/llm-docs/guides/graphql-server-specification.mdx +453 -0
  138. package/llm-docs/guides/network-layer.mdx +69 -0
  139. package/llm-docs/guides/persisted-queries.mdx +328 -0
  140. package/llm-docs/guides/relay-resolvers/context.mdx +99 -0
  141. package/llm-docs/guides/relay-resolvers/defining-fields.mdx +151 -0
  142. package/llm-docs/guides/relay-resolvers/defining-types.mdx +164 -0
  143. package/llm-docs/guides/relay-resolvers/deprecated.mdx +27 -0
  144. package/llm-docs/guides/relay-resolvers/derived-fields.mdx +127 -0
  145. package/llm-docs/guides/relay-resolvers/descriptions.mdx +44 -0
  146. package/llm-docs/guides/relay-resolvers/enabling.mdx +41 -0
  147. package/llm-docs/guides/relay-resolvers/errors.mdx +64 -0
  148. package/llm-docs/guides/relay-resolvers/field-arguments.mdx +63 -0
  149. package/llm-docs/guides/relay-resolvers/introduction.mdx +62 -0
  150. package/llm-docs/guides/relay-resolvers/limitations.mdx +30 -0
  151. package/llm-docs/guides/relay-resolvers/live-fields.mdx +164 -0
  152. package/llm-docs/guides/relay-resolvers/return-types.mdx +161 -0
  153. package/llm-docs/guides/relay-resolvers/suspense.mdx +41 -0
  154. package/llm-docs/guides/required-directive.mdx +240 -0
  155. package/llm-docs/guides/semantic-nullability.mdx +93 -0
  156. package/llm-docs/guides/testing-relay-components.mdx +642 -0
  157. package/llm-docs/guides/testing-relay-with-preloaded-queries.mdx +160 -0
  158. package/llm-docs/guides/throw-on-field-error-directive.mdx +58 -0
  159. package/llm-docs/guides/type-emission.mdx +414 -0
  160. package/llm-docs/home.mdx +32 -0
  161. package/llm-docs/principles-and-architecture/architecture-overview.mdx +24 -0
  162. package/llm-docs/principles-and-architecture/compiler-architecture.mdx +106 -0
  163. package/llm-docs/principles-and-architecture/runtime-architecture.mdx +249 -0
  164. package/llm-docs/principles-and-architecture/thinking-in-graphql.mdx +309 -0
  165. package/llm-docs/principles-and-architecture/thinking-in-relay.mdx +104 -0
  166. package/llm-docs/principles-and-architecture/videos.mdx +50 -0
  167. package/llm-docs/tutorial/arrays-lists.mdx +126 -0
  168. package/llm-docs/tutorial/fragments-1.mdx +487 -0
  169. package/llm-docs/tutorial/graphql.mdx +172 -0
  170. package/llm-docs/tutorial/interfaces-polymorphism.mdx +161 -0
  171. package/llm-docs/tutorial/intro.mdx +58 -0
  172. package/llm-docs/tutorial/mutations-updates.mdx +624 -0
  173. package/llm-docs/tutorial/organizing-mutations-queries-and-subscriptions.mdx +13 -0
  174. package/llm-docs/tutorial/queries-1.mdx +267 -0
  175. package/llm-docs/tutorial/queries-2.mdx +389 -0
  176. package/llm-docs/tutorial/refetchable-fragments.mdx +352 -0
  177. package/multi-actor-environment/ActorIdentifier.d.ts +17 -0
  178. package/multi-actor-environment/ActorIdentifier.js.flow +2 -2
  179. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +15 -15
  180. package/multi-actor-environment/ActorUtils.js.flow +1 -1
  181. package/multi-actor-environment/MultiActorEnvironment.d.ts +123 -0
  182. package/multi-actor-environment/MultiActorEnvironment.js.flow +32 -24
  183. package/multi-actor-environment/MultiActorEnvironmentTypes.d.ts +225 -0
  184. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +6 -6
  185. package/multi-actor-environment/index.d.ts +14 -0
  186. package/multi-actor-environment.d.ts +8 -0
  187. package/mutations/RelayDeclarativeMutationConfig.d.ts +70 -0
  188. package/mutations/RelayDeclarativeMutationConfig.js.flow +9 -9
  189. package/mutations/RelayRecordProxy.js.flow +8 -11
  190. package/mutations/RelayRecordSourceMutator.js.flow +4 -4
  191. package/mutations/RelayRecordSourceProxy.js.flow +4 -4
  192. package/mutations/RelayRecordSourceSelectorProxy.js.flow +6 -6
  193. package/mutations/applyOptimisticMutation.d.ts +25 -0
  194. package/mutations/applyOptimisticMutation.js.flow +2 -2
  195. package/mutations/commitLocalUpdate.d.ts +10 -0
  196. package/mutations/commitMutation.d.ts +48 -0
  197. package/mutations/commitMutation.js.flow +21 -17
  198. package/mutations/createUpdatableProxy.js.flow +19 -19
  199. package/mutations/readUpdatableFragment.js.flow +3 -3
  200. package/mutations/readUpdatableQuery.js.flow +3 -3
  201. package/mutations/validateMutation.js.flow +7 -7
  202. package/network/RelayNetwork.d.ts +12 -0
  203. package/network/RelayNetworkTypes.d.ts +145 -0
  204. package/network/RelayNetworkTypes.js.flow +18 -18
  205. package/network/RelayObservable.d.ts +197 -0
  206. package/network/RelayObservable.js.flow +32 -30
  207. package/network/RelayQueryResponseCache.d.ts +16 -0
  208. package/network/RelayQueryResponseCache.js.flow +3 -3
  209. package/network/wrapNetworkWithLogObserver.js.flow +1 -1
  210. package/package.json +2 -1
  211. package/query/GraphQLTag.d.ts +45 -0
  212. package/query/GraphQLTag.js.flow +22 -10
  213. package/query/fetchQuery.d.ts +21 -0
  214. package/query/fetchQuery.js.flow +23 -10
  215. package/query/fetchQueryInternal.d.ts +26 -0
  216. package/query/fetchQueryInternal.js.flow +4 -4
  217. package/query/fetchQuery_DEPRECATED.d.ts +17 -0
  218. package/query/fetchQuery_DEPRECATED.js.flow +1 -1
  219. package/store/ClientID.d.ts +14 -0
  220. package/store/DataChecker.js.flow +51 -15
  221. package/store/NormalizationEngine.js.flow +782 -0
  222. package/store/OperationExecutor.d.ts +51 -0
  223. package/store/OperationExecutor.js.flow +204 -98
  224. package/store/RelayConcreteVariables.js.flow +5 -5
  225. package/store/RelayErrorTrie.js.flow +12 -12
  226. package/store/RelayExperimentalGraphResponseHandler.js.flow +3 -3
  227. package/store/RelayExperimentalGraphResponseTransform.js.flow +10 -10
  228. package/store/RelayModernEnvironment.d.ts +97 -0
  229. package/store/RelayModernEnvironment.js.flow +58 -43
  230. package/store/RelayModernFragmentSpecResolver.js.flow +1 -1
  231. package/store/RelayModernOperationDescriptor.d.ts +28 -0
  232. package/store/RelayModernOperationDescriptor.js.flow +1 -1
  233. package/store/RelayModernRecord.d.ts +92 -0
  234. package/store/RelayModernRecord.js.flow +44 -20
  235. package/store/RelayModernSelector.d.ts +123 -0
  236. package/store/RelayModernSelector.js.flow +21 -21
  237. package/store/RelayModernStore.d.ts +57 -0
  238. package/store/RelayModernStore.js.flow +219 -58
  239. package/store/RelayOperationTracker.d.ts +29 -0
  240. package/store/RelayOperationTracker.js.flow +2 -2
  241. package/store/RelayOptimisticRecordSource.js.flow +2 -2
  242. package/store/RelayPublishQueue.js.flow +29 -20
  243. package/store/RelayReader.js.flow +129 -57
  244. package/store/RelayRecordSource.d.ts +26 -0
  245. package/store/RelayRecordSource.js.flow +10 -0
  246. package/store/RelayRecordState.d.ts +28 -0
  247. package/store/RelayRecordState.js.flow +1 -1
  248. package/store/RelayReferenceMarker.js.flow +5 -4
  249. package/store/RelayResponseNormalizer.d.ts +28 -0
  250. package/store/RelayResponseNormalizer.js.flow +130 -62
  251. package/store/RelayStoreSubscriptions.js.flow +52 -8
  252. package/store/RelayStoreTypes.d.ts +1327 -0
  253. package/store/RelayStoreTypes.js.flow +371 -278
  254. package/store/RelayStoreUtils.d.ts +86 -0
  255. package/store/RelayStoreUtils.js.flow +16 -8
  256. package/store/ResolverCache.js.flow +2 -2
  257. package/store/ResolverFragments.d.ts +43 -0
  258. package/store/ResolverFragments.js.flow +22 -14
  259. package/store/StoreInspector.js.flow +7 -8
  260. package/store/ViewerPattern.d.ts +11 -0
  261. package/store/cloneRelayHandleSourceField.js.flow +1 -1
  262. package/store/cloneRelayScalarHandleSourceField.js.flow +1 -1
  263. package/store/createFragmentSpecResolver.d.ts +16 -0
  264. package/store/createRelayContext.js.flow +1 -1
  265. package/store/createRelayLoggingContext.js.flow +4 -4
  266. package/store/defaultGetDataID.js.flow +2 -2
  267. package/store/isRelayModernEnvironment.d.ts +8 -0
  268. package/store/isRelayModernEnvironment.js.flow +4 -2
  269. package/store/live-resolvers/LiveResolverCache.js.flow +55 -20
  270. package/store/live-resolvers/LiveResolverSuspenseSentinel.js.flow +3 -3
  271. package/store/live-resolvers/getOutputTypeRecordIDs.js.flow +1 -1
  272. package/store/live-resolvers/isLiveStateValue.js.flow +2 -2
  273. package/store/live-resolvers/resolverDataInjector.d.ts +27 -0
  274. package/store/live-resolvers/resolverDataInjector.js.flow +8 -5
  275. package/store/observeFragmentExperimental.d.ts +46 -0
  276. package/store/observeFragmentExperimental.js.flow +50 -21
  277. package/store/observeQueryExperimental.d.ts +30 -0
  278. package/store/observeQueryExperimental.js.flow +5 -5
  279. package/store/readInlineData.d.ts +19 -0
  280. package/store/readInlineData.js.flow +5 -5
  281. package/store/waitForFragmentExperimental.d.ts +49 -0
  282. package/store/waitForFragmentExperimental.js.flow +3 -3
  283. package/subscription/requestSubscription.d.ts +27 -0
  284. package/subscription/requestSubscription.js.flow +10 -10
  285. package/util/JSResourceTypes.flow.js.flow +4 -4
  286. package/util/NormalizationNode.d.ts +235 -0
  287. package/util/NormalizationNode.js.flow +127 -123
  288. package/util/ReaderNode.d.ts +264 -0
  289. package/util/ReaderNode.js.flow +156 -151
  290. package/util/RelayConcreteNode.d.ts +120 -0
  291. package/util/RelayConcreteNode.js.flow +32 -32
  292. package/util/RelayError.d.ts +13 -0
  293. package/util/RelayError.js.flow +4 -1
  294. package/util/RelayFeatureFlags.d.ts +40 -0
  295. package/util/RelayFeatureFlags.js.flow +21 -1
  296. package/util/RelayProfiler.d.ts +121 -0
  297. package/util/RelayProfiler.js.flow +1 -1
  298. package/util/RelayReplaySubject.d.ts +25 -0
  299. package/util/RelayReplaySubject.js.flow +3 -3
  300. package/util/RelayRuntimeTypes.d.ts +59 -0
  301. package/util/RelayRuntimeTypes.js.flow +36 -33
  302. package/util/createPayloadFor3DField.d.ts +17 -0
  303. package/util/createPayloadFor3DField.js.flow +9 -5
  304. package/util/deepFreeze.d.ts +8 -0
  305. package/util/deepFreeze.js.flow +2 -2
  306. package/util/getFragmentIdentifier.d.ts +10 -0
  307. package/util/getFragmentIdentifier.js.flow +1 -1
  308. package/util/getPaginationMetadata.d.ts +20 -0
  309. package/util/getPaginationMetadata.js.flow +1 -1
  310. package/util/getPaginationVariables.d.ts +20 -0
  311. package/util/getPaginationVariables.js.flow +1 -1
  312. package/util/getPendingOperationsForFragment.d.ts +18 -0
  313. package/util/getPendingOperationsForFragment.js.flow +2 -2
  314. package/util/getRefetchMetadata.d.ts +19 -0
  315. package/util/getRefetchMetadata.js.flow +6 -5
  316. package/util/getRelayHandleKey.d.ts +8 -0
  317. package/util/getRequestIdentifier.d.ts +17 -0
  318. package/util/getValueAtPath.d.ts +8 -0
  319. package/util/getValueAtPath.js.flow +3 -3
  320. package/util/handlePotentialSnapshotErrors.d.ts +14 -0
  321. package/util/handlePotentialSnapshotErrors.js.flow +5 -5
  322. package/util/isEmptyObject.js.flow +1 -1
  323. package/util/isPromise.d.ts +8 -0
  324. package/util/isPromise.js.flow +2 -2
  325. package/util/isScalarAndEqual.d.ts +8 -0
  326. package/util/isScalarAndEqual.js.flow +1 -1
  327. package/util/recycleNodesInto.d.ts +8 -0
  328. package/util/recycleNodesInto.js.flow +2 -2
  329. package/util/registerEnvironmentWithDevTools.js.flow +1 -1
  330. package/util/shallowFreeze.js.flow +1 -1
  331. package/util/stableCopy.d.ts +8 -0
  332. package/util/stableCopy.js.flow +5 -5
  333. package/util/withProvidedVariables.d.ts +19 -0
  334. package/util/withProvidedVariables.js.flow +14 -10
@@ -0,0 +1,328 @@
1
+ ---
2
+ id: persisted-queries
3
+ title: Persisted Queries
4
+ slug: /guides/persisted-queries/
5
+ description: Relay guide to persisted queries
6
+ keywords:
7
+ - persisted
8
+ ---
9
+
10
+ import DocsRating from '@site/src/core/DocsRating';
11
+ import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
12
+
13
+ <FbInternalOnly>
14
+
15
+ :::tip
16
+ At Meta, persistence is handled by the `relay` command for you. You likely do not need to worry about the contents of this guide.
17
+ :::
18
+
19
+ </FbInternalOnly>
20
+
21
+ The Relay compiler supports persisted queries. This is useful because:
22
+
23
+ - The client operation text becomes just an md5 hash which is usually shorter than the real
24
+ query string. This saves upload bytes from the client to the server.
25
+
26
+ - The server can now allowlist queries which improves security by restricting the operations
27
+ that can be executed by a client.
28
+
29
+ <OssOnly>
30
+
31
+ ## Usage on the client
32
+
33
+ ### The `persistConfig` option
34
+
35
+ In the `relay` configuration section of your `package.json` you'll need specify
36
+ "persistConfig".
37
+
38
+ ```
39
+ "scripts": {
40
+ "relay": "relay-compiler",
41
+ "relay-persisting": "node relayLocalPersisting.js"
42
+ },
43
+ "relay": {
44
+ "src": "./src",
45
+ "schema": "./schema.graphql",
46
+ "persistConfig": {
47
+ "url": "http://localhost:2999",
48
+ "params": {}
49
+ }
50
+ }
51
+ ```
52
+
53
+ Specifying `persistConfig` in the config will do the following:
54
+
55
+ 1. It converts all query and mutation operation texts to md5 hashes.
56
+
57
+ For example without `persistConfig`, a generated `ConcreteRequest` might look
58
+ like below:
59
+
60
+ ```javascript
61
+ const node/*: ConcreteRequest*/ = (function(){
62
+ //... excluded for brevity
63
+ return {
64
+ "kind": "Request",
65
+ "operationKind": "query",
66
+ "name": "TodoItemRefetchQuery",
67
+ "id": null, // NOTE: id is null
68
+ "text": "query TodoItemRefetchQuery(\n $itemID: ID!\n) {\n node(id: $itemID) {\n ...TodoItem_item_2FOrhs\n }\n}\n\nfragment TodoItem_item_2FOrhs on Todo {\n text\n isComplete\n}\n",
69
+ //... excluded for brevity
70
+ };
71
+ })();
72
+
73
+ ```
74
+
75
+ With `persistConfig` this becomes:
76
+
77
+ ```javascript
78
+ const node/*: ConcreteRequest*/ = (function(){
79
+ //... excluded for brevity
80
+ return {
81
+ "kind": "Request",
82
+ "operationKind": "query",
83
+ "name": "TodoItemRefetchQuery",
84
+ "id": "3be4abb81fa595e25eb725b2c6a87508", // NOTE: id is now an md5 hash
85
+ // of the query text
86
+ "text": null, // NOTE: text is null now
87
+ //... excluded for brevity
88
+ };
89
+ })();
90
+
91
+ ```
92
+
93
+ 2. It will send an HTTP POST request with a `text` parameter to the
94
+ specified `url`.
95
+ You can also add additional request body parameters via the `params` option.
96
+
97
+ ```
98
+ "scripts": {
99
+ "relay": "relay-compiler"
100
+ },
101
+ "relay": {
102
+ "src": "./src",
103
+ "schema": "./schema.graphql",
104
+ "persistConfig": {
105
+ "url": "http://localhost:2999",
106
+ "params": {}
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Local Persisted Queries
112
+
113
+ With the following config, you can generate a local JSON file which contains a map of `operation_id => full operation text`.
114
+
115
+ ```
116
+ "scripts": {
117
+ "relay": "relay-compiler"
118
+ },
119
+ "relay": {
120
+ "src": "./src",
121
+ "schema": "./schema.graphql",
122
+ "persistConfig": {
123
+ "file": "./persisted_queries.json",
124
+ "algorithm": "MD5" // this can be one of MD5, SHA256, SHA1
125
+ }
126
+ }
127
+ ```
128
+
129
+ Ideally, you'll take this file and ship it to your server at deploy time so your server knows about all the queries it could possibly receive. If you don't want to do that, you'll have to implement the [Automatic Persisted Queries handshake](https://www.apollographql.com/docs/apollo-server/performance/apq/).
130
+
131
+ #### Tradeoffs
132
+
133
+ - ✅ If your server's persisted query datastore gets wiped, you can recover automatically through your client's requests.
134
+ - ❌ When there's a cache miss, it'll cost you an extra round trip to the server.
135
+ - ❌ You'll have to ship your `persisted_queries.json` file to the browser which will increase your bundle size.
136
+
137
+ ### Example implementation of `relayLocalPersisting.js`
138
+
139
+ Here's an example of a simple persist server that will save query text to the `queryMap.json` file.
140
+
141
+
142
+ ```javascript
143
+ const http = require('http');
144
+ const crypto = require('crypto');
145
+ const fs = require('fs');
146
+
147
+ function md5(input) {
148
+ return crypto.createHash('md5').update(input).digest('hex');
149
+ }
150
+
151
+ class QueryMap {
152
+ constructor(fileMapName) {
153
+ this._fileMapName = fileMapName;
154
+ this._queryMap = new Map(JSON.parse(fs.readFileSync(this._fileMapName)));
155
+ }
156
+
157
+ _flush() {
158
+ const data = JSON.stringify(Array.from(this._queryMap.entries()));
159
+ fs.writeFileSync(this._fileMapName, data);
160
+ }
161
+
162
+ saveQuery(text) {
163
+ const id = md5(text);
164
+ this._queryMap.set(id, text);
165
+ this._flush();
166
+ return id;
167
+ }
168
+ }
169
+
170
+ const queryMap = new QueryMap('./queryMap.json');
171
+
172
+ async function requestListener(req, res) {
173
+ if (req.method === 'POST') {
174
+ const buffers = [];
175
+ for await (const chunk of req) {
176
+ buffers.push(chunk);
177
+ }
178
+ const data = Buffer.concat(buffers).toString();
179
+ res.writeHead(200, {
180
+ 'Content-Type': 'application/json'
181
+ });
182
+ try {
183
+ if (req.headers['content-type'] !== 'application/x-www-form-urlencoded') {
184
+ throw new Error(
185
+ 'Only "application/x-www-form-urlencoded" requests are supported.'
186
+ );
187
+ }
188
+ const text = new URLSearchParams(data).get('text');
189
+ if (text == null) {
190
+ throw new Error('Expected to have `text` parameter in the POST.');
191
+ }
192
+ const id = queryMap.saveQuery(text);
193
+ res.end(JSON.stringify({"id": id}));
194
+ } catch (e) {
195
+ console.error(e);
196
+ res.writeHead(400);
197
+ res.end(`Unable to save query: ${e}.`);
198
+ }
199
+ } else {
200
+ res.writeHead(400);
201
+ res.end("Request is not supported.")
202
+ }
203
+ }
204
+
205
+ const PORT = 2999;
206
+ const server = http.createServer(requestListener);
207
+ server.listen(PORT);
208
+
209
+ console.log(`Relay persisting server listening on ${PORT} port.`);
210
+ ```
211
+
212
+ The example above writes the complete query map file to `./queryMap.json`.
213
+ To use this, you'll need to update `package.json`:
214
+
215
+
216
+ ```
217
+ "scripts": {
218
+ "persist-server": "node ./relayLocalPersisting.js",
219
+ "relay": "relay-compiler"
220
+ }
221
+ ```
222
+
223
+ </OssOnly>
224
+
225
+ ### Network layer changes
226
+
227
+ You'll need to modify your network layer fetch implementation to pass an ID parameter in the POST body (e.g., `doc_id`) instead of a query parameter:
228
+
229
+ ```javascript
230
+ function fetchQuery(operation, variables) {
231
+ return fetch('/graphql', {
232
+ method: 'POST',
233
+ headers: {
234
+ 'content-type': 'application/json'
235
+ },
236
+ body: JSON.stringify({
237
+ doc_id: operation.id, // NOTE: pass md5 hash to the server
238
+ // query: operation.text, // this is now obsolete because text is null
239
+ variables,
240
+ }),
241
+ }).then(response => {
242
+ return response.json();
243
+ });
244
+ }
245
+ ```
246
+
247
+
248
+ ## Executing Persisted Queries on the Server
249
+
250
+ <FbInternalOnly>
251
+
252
+ Your server should then look up the query referenced by `doc_id` when responding to this request.
253
+
254
+ </FbInternalOnly>
255
+
256
+ <OssOnly>
257
+
258
+ To execute client requests that send persisted queries instead of query text, your server will need to be able
259
+ to lookup the query text corresponding to each ID. Typically this will involve saving the output of the `queryMap.json` JSON file to a database or some other storage mechanism, and retrieving the corresponding text for the ID specified by a client.
260
+
261
+ Additionally, your implementation of `relayLocalPersisting.js` could directly save queries to the database or other storage.
262
+
263
+ For universal applications where the client and server code are in one project, this is not an issue since you can place
264
+ the query map file in a common location accessible to both the client and the server.
265
+
266
+ ### Compile time push
267
+
268
+ For applications where the client and server projects are separate, one option is to have an additional npm run script
269
+ to push the query map at compile time to a location accessible by your server:
270
+
271
+ ```javascript
272
+ "scripts": {
273
+ "push-queries": "node ./pushQueries.js",
274
+ "persist-server": "node ./relayLocalPersisting.js",
275
+ "relay": "relay-compiler && npm run push-queries"
276
+ }
277
+ ```
278
+
279
+ Some possibilities of what you can do in `./pushQueries.js`:
280
+
281
+ - `git push` to your server repo.
282
+
283
+ - Save the query maps to a database.
284
+
285
+ ### Run time push
286
+
287
+ A second more complex option is to push your query maps to the server at runtime, without the server knowing the query IDs at the start.
288
+ The client optimistically sends a query ID to the server, which does not have the query map. The server then in turn requests
289
+ for the full query text from the client so it can cache the query map for subsequent requests. This is a more complex approach
290
+ requiring the client and server to interact to exchange the query maps.
291
+
292
+ ### Simple server example
293
+
294
+ Once your server has access to the query map, you can perform the mapping. The solution varies depending on the server and
295
+ database technologies you use, so we'll just cover the most common and basic example here.
296
+
297
+ If you use `express-graphql` and have access to the query map file, you can import it directly and
298
+ perform the matching using the `persistedQueries` middleware from [express-graphql-persisted-queries](https://github.com/kyarik/express-graphql-persisted-queries).
299
+
300
+ ```javascript
301
+ import express from 'express';
302
+ import {graphqlHTTP} from 'express-graphql';
303
+ import {persistedQueries} from 'express-graphql-persisted-queries';
304
+ import queryMap from './path/to/queryMap.json';
305
+
306
+ const app = express();
307
+
308
+ app.use(
309
+ '/graphql',
310
+ persistedQueries({
311
+ queryMap,
312
+ queryIdKey: 'doc_id',
313
+ }),
314
+ graphqlHTTP({schema}),
315
+ );
316
+ ```
317
+
318
+ ## Using `persistConfig` and `--watch`
319
+
320
+ It is possible to continuously generate the query map files by using the `persistConfig` and `--watch` options simultaneously.
321
+ This only makes sense for universal applications i.e. if your client and server code are in a single project
322
+ and you run them both together on localhost during development. Furthermore, in order for the server to pick up changes
323
+ to the `queryMap.json`, you'll need to have server side hot-reloading set up. The details on how to set this up
324
+ are out of the scope of this document.
325
+
326
+ </OssOnly>
327
+
328
+ <DocsRating />
@@ -0,0 +1,99 @@
1
+ ---
2
+ id: context
3
+ title: "Context"
4
+ slug: /guides/relay-resolvers/context
5
+ description: Context in Relay Resolvers
6
+ ---
7
+ import {FbInternalOnly, fbContent} from 'docusaurus-plugin-internaldocs-fb/internal';
8
+ import Tabs from '@theme/Tabs';
9
+ import TabItem from '@theme/TabItem';
10
+
11
+ In order to pass a service, or other values to be shared with all resolvers, the `RelayModernStore` provides a means of passing context. This gets passed to the third argument of all resolvers (live and non-live). This context argument analogous to the [context argument](https://graphql.org/learn/execution/#root-fields--resolvers) used on the server which usually holds things like the database connection.
12
+
13
+ ## Setup
14
+
15
+ In order to pass context to live resolvers, pass a `resolverContext` argument to the initialization of `RelayModernStore` before creating the environment:
16
+
17
+ ```js
18
+ const store = new RelayModernStore(source, {
19
+ resolverContext: {
20
+ store: customStore,
21
+ },
22
+ });
23
+ ```
24
+
25
+ ## Usage in Resolvers
26
+
27
+ <Tabs
28
+ groupId="resolver"
29
+ defaultValue="JavaScript"
30
+ values={fbContent({
31
+ internal: [
32
+ {label: 'JavaScript', value: 'JavaScript'},
33
+ {label: 'Flow', value: 'Flow'},
34
+ ],
35
+ external: [
36
+ {label: 'JavaScript', value: 'JavaScript'},
37
+ {label: 'Flow', value: 'Flow'},
38
+ ]
39
+ })}>
40
+ <TabItem value="JavaScript">
41
+
42
+ The last argument in a resolver will contain the context type which contains the value passed into the store on initialization. If the resolver is on a model type or reads a `@rootFragment`, the context value will be the third argument. If the resolver is _not_ on a model type and does _not_ read a `@rootFragment` the context value will be passed as the third argument. Relay's generated artifacts will include generated type assertions to check that your resolver is typed correctly.
43
+
44
+ ```js
45
+ import type { LiveState } from 'relay-runtime';
46
+
47
+ /**
48
+ * @relayField Query.counter: Int
49
+ * @live
50
+ */
51
+ export function counter(
52
+ _args,
53
+ context
54
+ ) {
55
+ return {
56
+ read: () => context.store.getState().counter,
57
+ subscribe: (callback) => {
58
+ return context.store.subscribe(callback);
59
+ },
60
+ };
61
+ }
62
+ ```
63
+
64
+ </TabItem>
65
+
66
+ <TabItem value="Flow">
67
+
68
+ Context is not currently supported in Flow
69
+
70
+ </TabItem>
71
+ </Tabs>
72
+
73
+ ## Type Checking
74
+
75
+ In order to ensure that the resolver is implemented with the correct types, pass a `resolverContextType` in the project config. This parameter expects a type name and a `path` to import from:
76
+
77
+ ```json
78
+ {
79
+ "name": "project",
80
+ "language": "flow",
81
+ "resolverContextType": {
82
+ "name": "IResolverContextType",
83
+ "path": "path/to/file/IResolverContextType"
84
+ }
85
+ }
86
+ ```
87
+
88
+ To import from a package, use the following syntax for a `package` import:
89
+
90
+ ```json
91
+ {
92
+ "name": "project",
93
+ "language": "flow",
94
+ "resolverContextType": {
95
+ "name": "IResolverContextType",
96
+ "package": "@package/name"
97
+ }
98
+ }
99
+ ```
@@ -0,0 +1,151 @@
1
+ ---
2
+ id: defining-fields
3
+ title: "Defining Fields"
4
+ slug: /guides/relay-resolvers/defining-fields/
5
+ description: How to define fields for your client state schema using Relay Resolvers
6
+ ---
7
+ import {FbInternalOnly, fbContent} from 'docusaurus-plugin-internaldocs-fb/internal';
8
+ import Tabs from '@theme/Tabs';
9
+ import TabItem from '@theme/TabItem';
10
+
11
+ Defining fields on a client type is as simple as defining a resolver function which accepts an instance of your model type as its first argument and returns the field value. Note that the exported function name must match the field name.
12
+
13
+ ## Syntax
14
+
15
+ Relay resolvers are marked via docblocks above a resolver function. `@relayField` is the tag used to define a field on a type. To define a field on a GraphQL model type `TypeName`:
16
+
17
+ <Tabs
18
+ groupId="resolver"
19
+ defaultValue="Docblock"
20
+ values={fbContent({
21
+ internal: [
22
+ {label: 'Docblock', value: 'Docblock'},
23
+ {label: 'Flow', value: 'Flow'},
24
+ ],
25
+ external: [
26
+ {label: 'Docblock', value: 'Docblock'},
27
+ ]
28
+ })}>
29
+ <TabItem value="Docblock">
30
+
31
+ Add `TypeName` followed by a dot followed by the field definition using GraphQL's schema definition language: https://spec.graphql.org/June2018/#FieldDefinition
32
+
33
+ ```js
34
+ /**
35
+ * @relayField TypeName.fieldName(arg1: ArgTypeName): FieldTypeName
36
+ */
37
+ ```
38
+
39
+ </TabItem>
40
+
41
+ <TabItem value="Flow">
42
+ <FbInternalOnly>
43
+
44
+ Import and use the Flow type for the object, Relay finds the GraphQL type linked to `TypeName`, and use the function name as the field name
45
+
46
+ ```tsx
47
+ import {TypeName} from 'TypeObject';
48
+
49
+ /**
50
+ * @relayField
51
+ */
52
+ export function fieldName(user: TypeName): string {
53
+ return user.name;
54
+ }
55
+ ```
56
+
57
+ </FbInternalOnly>
58
+ </TabItem>
59
+ </Tabs>
60
+
61
+ A simple field might look something like this:
62
+
63
+ <Tabs
64
+ groupId="resolver"
65
+ defaultValue="Docblock"
66
+ values={fbContent({
67
+ internal: [
68
+ {label: 'Docblock', value: 'Docblock'},
69
+ {label: 'Flow', value: 'Flow'},
70
+ ],
71
+ external: [
72
+ {label: 'Docblock', value: 'Docblock'},
73
+ ]
74
+ })}>
75
+ <TabItem value="Docblock">
76
+
77
+ ```tsx
78
+ /**
79
+ * @relayField User.name: String
80
+ */
81
+ export function name(user: UserModel): string {
82
+ return user.name;
83
+ }
84
+ ```
85
+ </TabItem>
86
+
87
+ <TabItem value="Flow">
88
+ <FbInternalOnly>
89
+
90
+ ```tsx
91
+ /**
92
+ * @relayField
93
+ */
94
+ export function name(user: UserModel): string {
95
+ return user.name;
96
+ }
97
+ ```
98
+
99
+ </FbInternalOnly>
100
+ </TabItem>
101
+ </Tabs>
102
+
103
+ :::note
104
+ Relay will take care of efficiently recomputing resolvers when any of their inputs (in this case the model instance) change, so you don’t need to worry about memoizing your resolver function.
105
+ :::
106
+
107
+ This is just a simple resolver that reads from the model type and returns a scalar value. To learn about the full menu of capabilities that resolver fields support see:
108
+
109
+ * [Resolver Return Types](./return-types.mdx)
110
+ * [Field Arguments](./field-arguments.mdx)
111
+ * [Live Fields](./live-fields.mdx)
112
+ * [Derived Fields](./derived-fields.mdx)
113
+
114
+ <FbInternalOnly>
115
+
116
+ ## Simplified Syntax for Property Lookups
117
+
118
+ If you have a ["weak" type](./defining-types.mdx#defining-a-weak-type), you can easily define a simple resolver that just returns a property from the underlying model. For example, take a resolver being defined on the `UserModel` that looks like:
119
+ ```tsx
120
+ /**
121
+ * @relayField
122
+ */
123
+ export function name(user: UserModel): string {
124
+ return user.name;
125
+ }
126
+ ```
127
+
128
+ When defining the weak type, this resolver can by automatically generated by using a docblock with `@gqlField` over the field you want to expose.
129
+ ```tsx
130
+ /**
131
+ * @relayType
132
+ */
133
+ export type UserModel = {
134
+ /**
135
+ * @gqlField
136
+ */
137
+ name: string,
138
+ }
139
+ ```
140
+
141
+ You can optionally include a description or `@deprecated` tag in the docblock
142
+ ```tsx
143
+ /**
144
+ * @gqlField
145
+ * @deprecated Do not use this field anymore
146
+ *
147
+ * This is a description. Include more information
148
+ * about your field here.
149
+ */
150
+ ```
151
+ </FbInternalOnly>