@apollo/client 4.3.0-alpha.1 → 4.3.0-alpha.11
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.
- package/CHANGELOG.md +503 -0
- package/README.md +3 -7
- package/__cjs/cache/core/Scalar.cjs +36 -0
- package/__cjs/cache/core/Scalar.cjs.map +1 -0
- package/__cjs/cache/core/Scalar.d.cts +19 -0
- package/__cjs/cache/core/cache.cjs +32 -1
- package/__cjs/cache/core/cache.cjs.map +1 -1
- package/__cjs/cache/core/cache.d.cts +89 -6
- package/__cjs/cache/core/types/Cache.d.cts +25 -0
- package/__cjs/cache/index.cjs +3 -1
- package/__cjs/cache/index.cjs.map +1 -1
- package/__cjs/cache/index.d.cts +3 -2
- package/__cjs/cache/inmemory/entityStore.cjs +48 -5
- package/__cjs/cache/inmemory/entityStore.cjs.map +1 -1
- package/__cjs/cache/inmemory/entityStore.d.cts +3 -0
- package/__cjs/cache/inmemory/helpers.d.cts +9 -1
- package/__cjs/cache/inmemory/inMemoryCache.cjs +83 -4
- package/__cjs/cache/inmemory/inMemoryCache.cjs.map +1 -1
- package/__cjs/cache/inmemory/inMemoryCache.d.cts +44 -5
- package/__cjs/cache/inmemory/key-extractor.cjs +1 -1
- package/__cjs/cache/inmemory/policies.cjs +35 -6
- package/__cjs/cache/inmemory/policies.cjs.map +1 -1
- package/__cjs/cache/inmemory/policies.d.cts +4 -1
- package/__cjs/cache/inmemory/readFromStore.cjs +490 -49
- package/__cjs/cache/inmemory/readFromStore.cjs.map +1 -1
- package/__cjs/cache/inmemory/readFromStore.d.cts +11 -2
- package/__cjs/cache/inmemory/types.d.cts +29 -4
- package/__cjs/cache/inmemory/writeToStore.cjs +6 -6
- package/__cjs/cache/inmemory/writeToStore.cjs.map +1 -1
- package/__cjs/core/ApolloClient.cjs +37 -38
- package/__cjs/core/ApolloClient.cjs.map +1 -1
- package/__cjs/core/ApolloClient.d.cts +44 -10
- package/__cjs/core/ObservableQuery.cjs +228 -76
- package/__cjs/core/ObservableQuery.cjs.map +1 -1
- package/__cjs/core/ObservableQuery.d.cts +16 -8
- package/__cjs/core/QueryInfo.cjs +178 -190
- package/__cjs/core/QueryInfo.cjs.map +1 -1
- package/__cjs/core/QueryInfo.d.cts +16 -21
- package/__cjs/core/QueryManager.cjs +88 -59
- package/__cjs/core/QueryManager.cjs.map +1 -1
- package/__cjs/core/QueryManager.d.cts +1 -3
- package/__cjs/core/RefetchEventManager.cjs +3 -3
- package/__cjs/core/dataStateErrorCache.cjs +12 -0
- package/__cjs/core/dataStateErrorCache.cjs.map +1 -0
- package/__cjs/core/dataStateErrorCache.d.cts +3 -0
- package/__cjs/core/index.cjs +2 -1
- package/__cjs/core/index.cjs.map +1 -1
- package/__cjs/core/index.d.cts +4 -3
- package/__cjs/core/types.d.cts +10 -3
- package/__cjs/incremental/GraphQLCodegenIncremental.cjs +3 -0
- package/__cjs/incremental/GraphQLCodegenIncremental.cjs.map +1 -0
- package/__cjs/incremental/GraphQLCodegenIncremental.d.cts +55 -0
- package/__cjs/incremental/handlers/defer20220824.cjs.map +1 -1
- package/__cjs/incremental/handlers/defer20220824.d.cts +2 -4
- package/__cjs/incremental/handlers/graphql17Alpha9.cjs +47 -16
- package/__cjs/incremental/handlers/graphql17Alpha9.cjs.map +1 -1
- package/__cjs/incremental/handlers/graphql17Alpha9.d.cts +29 -6
- package/__cjs/incremental/handlers/notImplemented.cjs +1 -1
- package/__cjs/incremental/index.cjs.map +1 -1
- package/__cjs/incremental/index.d.cts +1 -0
- package/__cjs/{utilities/internal/types/NoInfer.cjs → incremental/internal/types.cjs} +1 -1
- package/__cjs/incremental/internal/types.cjs.map +1 -0
- package/__cjs/incremental/internal/types.d.cts +17 -0
- package/__cjs/incremental/types.d.cts +55 -4
- package/__cjs/invariantErrorCodes.cjs +167 -112
- package/__cjs/link/core/ApolloLink.cjs +3 -3
- package/__cjs/link/http/checkFetcher.cjs +1 -1
- package/__cjs/link/http/parseAndCheckHttpResponse.cjs +2 -2
- package/__cjs/link/http/parseAndCheckHttpResponse.cjs.map +1 -1
- package/__cjs/link/persisted-queries/index.cjs +2 -2
- package/__cjs/link/ws/index.cjs +1 -1
- package/__cjs/local-state/LocalState.cjs +11 -11
- package/__cjs/local-state/LocalState.cjs.map +1 -1
- package/__cjs/local-state/LocalState.d.cts +1 -1
- package/__cjs/masking/internal/types.d.cts +1 -2
- package/__cjs/masking/maskDefinition.cjs +2 -2
- package/__cjs/masking/maskFragment.cjs +2 -2
- package/__cjs/masking/maskOperation.cjs +1 -1
- package/__cjs/masking/utils.cjs +3 -3
- package/__cjs/react/context/ApolloContext.cjs +1 -1
- package/__cjs/react/context/ApolloProvider.cjs +1 -1
- package/__cjs/react/hooks/internal/validateSuspenseHookOptions.cjs +2 -2
- package/__cjs/react/hooks/useApolloClient.cjs +1 -1
- package/__cjs/react/hooks/useBackgroundQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useBackgroundQuery.d.cts +100 -47
- package/__cjs/react/hooks/useFragment.cjs.map +1 -1
- package/__cjs/react/hooks/useFragment.d.cts +0 -1
- package/__cjs/react/hooks/useLazyQuery.cjs +2 -2
- package/__cjs/react/hooks/useLazyQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useLazyQuery.d.cts +40 -34
- package/__cjs/react/hooks/useLoadableQuery.cjs +2 -2
- package/__cjs/react/hooks/useLoadableQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useLoadableQuery.d.cts +23 -15
- package/__cjs/react/hooks/useMutation.cjs.map +1 -1
- package/__cjs/react/hooks/useMutation.d.cts +10 -7
- package/__cjs/react/hooks/useQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useQuery.d.cts +74 -32
- package/__cjs/react/hooks/useQueryRefHandlers.cjs.map +1 -1
- package/__cjs/react/hooks/useSubscription.cjs +7 -3
- package/__cjs/react/hooks/useSubscription.cjs.map +1 -1
- package/__cjs/react/hooks/useSubscription.d.cts +7 -4
- package/__cjs/react/hooks/useSuspenseFragment.cjs.map +1 -1
- package/__cjs/react/hooks/useSuspenseFragment.d.cts +1 -1
- package/__cjs/react/hooks/useSuspenseQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useSuspenseQuery.d.cts +83 -34
- package/__cjs/react/hooks/useSyncExternalStore.cjs +1 -1
- package/__cjs/react/internal/cache/QueryReference.cjs +1 -1
- package/__cjs/react/internal/cache/QueryReference.cjs.map +1 -1
- package/__cjs/react/internal/types.d.cts +14 -3
- package/__cjs/react/query-preloader/createQueryPreloader.cjs.map +1 -1
- package/__cjs/react/query-preloader/createQueryPreloader.d.cts +20 -5
- package/__cjs/react/ssr/prerenderStatic.cjs +2 -2
- package/__cjs/testing/core/mocking/mockLink.cjs +25 -5
- package/__cjs/testing/core/mocking/mockLink.cjs.map +1 -1
- package/__cjs/testing/core/mocking/mockLink.d.cts +1 -2
- package/__cjs/utilities/caching/sizes.cjs.map +1 -1
- package/__cjs/utilities/caching/sizes.d.cts +39 -1
- package/__cjs/utilities/graphql/DocumentTransform.cjs +1 -1
- package/__cjs/utilities/index.cjs.map +1 -1
- package/__cjs/utilities/index.d.cts +1 -0
- package/__cjs/utilities/internal/StreamArrayState.cjs +27 -0
- package/__cjs/utilities/internal/StreamArrayState.cjs.map +1 -0
- package/__cjs/utilities/internal/StreamArrayState.d.cts +12 -0
- package/__cjs/utilities/internal/addDeferFragmentLabels.cjs +33 -0
- package/__cjs/utilities/internal/addDeferFragmentLabels.cjs.map +1 -0
- package/__cjs/utilities/internal/addDeferFragmentLabels.d.cts +3 -0
- package/__cjs/utilities/internal/capitalize.cjs +12 -0
- package/__cjs/utilities/internal/capitalize.cjs.map +1 -0
- package/__cjs/utilities/internal/capitalize.d.cts +7 -0
- package/__cjs/utilities/internal/coerceScalarFieldsToParsed.cjs +69 -0
- package/__cjs/utilities/internal/coerceScalarFieldsToParsed.cjs.map +1 -0
- package/__cjs/utilities/internal/coerceScalarFieldsToParsed.d.cts +9 -0
- package/__cjs/utilities/internal/constants.cjs +20 -1
- package/__cjs/utilities/internal/constants.cjs.map +1 -1
- package/__cjs/utilities/internal/constants.d.cts +19 -0
- package/__cjs/utilities/internal/getDirectiveArgValue.cjs +19 -0
- package/__cjs/utilities/internal/getDirectiveArgValue.cjs.map +1 -0
- package/__cjs/utilities/internal/getDirectiveArgValue.d.cts +9 -0
- package/__cjs/utilities/internal/getFragmentDefinition.cjs +3 -3
- package/__cjs/utilities/internal/getFragmentFromSelection.cjs +2 -2
- package/__cjs/utilities/internal/getFragmentFromSelection.cjs.map +1 -1
- package/__cjs/utilities/internal/getFragmentQueryDocument.cjs +2 -2
- package/__cjs/utilities/internal/getMainDefinition.cjs +1 -1
- package/__cjs/utilities/internal/getMemoryInternals.cjs +6 -0
- package/__cjs/utilities/internal/getMemoryInternals.cjs.map +1 -1
- package/__cjs/utilities/internal/getMemoryInternals.d.cts +4 -0
- package/__cjs/utilities/internal/getQueryDefinition.cjs +1 -1
- package/__cjs/utilities/internal/getUnwrappedType.cjs +20 -0
- package/__cjs/utilities/internal/getUnwrappedType.cjs.map +1 -0
- package/__cjs/utilities/internal/getUnwrappedType.d.cts +8 -0
- package/__cjs/utilities/internal/index.cjs +25 -2
- package/__cjs/utilities/internal/index.cjs.map +1 -1
- package/__cjs/utilities/internal/index.d.cts +16 -2
- package/__cjs/utilities/internal/isDeferredFragment.cjs +38 -0
- package/__cjs/utilities/internal/isDeferredFragment.cjs.map +1 -0
- package/__cjs/utilities/internal/isDeferredFragment.d.cts +9 -0
- package/__cjs/utilities/internal/isStreamField.cjs +37 -0
- package/__cjs/utilities/internal/isStreamField.cjs.map +1 -0
- package/__cjs/utilities/internal/isStreamField.d.cts +9 -0
- package/__cjs/utilities/internal/isTypenameField.cjs +7 -0
- package/__cjs/utilities/internal/isTypenameField.cjs.map +1 -0
- package/__cjs/utilities/internal/isTypenameField.d.cts +3 -0
- package/__cjs/utilities/internal/makeStreamInfoTrie.cjs +17 -0
- package/__cjs/utilities/internal/makeStreamInfoTrie.cjs.map +1 -0
- package/__cjs/utilities/internal/makeStreamInfoTrie.d.cts +8 -0
- package/__cjs/utilities/internal/removeDirectivesFromDocument.cjs +1 -1
- package/__cjs/utilities/internal/shouldInclude.cjs +4 -4
- package/__cjs/utilities/internal/toDiffWithDataState.cjs +20 -0
- package/__cjs/utilities/internal/toDiffWithDataState.cjs.map +1 -0
- package/__cjs/utilities/internal/toDiffWithDataState.d.cts +8 -0
- package/__cjs/utilities/internal/types/DeferInfo.cjs +3 -0
- package/__cjs/utilities/internal/types/DeferInfo.cjs.map +1 -0
- package/__cjs/utilities/internal/types/DeferInfo.d.cts +10 -0
- package/__cjs/utilities/internal/types/Exact.cjs +3 -0
- package/__cjs/utilities/internal/types/Exact.cjs.map +1 -0
- package/__cjs/utilities/internal/types/Exact.d.cts +2 -0
- package/__cjs/utilities/internal/types/IsLooselyEqual.cjs +3 -0
- package/__cjs/utilities/internal/types/IsLooselyEqual.cjs.map +1 -0
- package/__cjs/utilities/internal/types/IsLooselyEqual.d.cts +10 -0
- package/__cjs/utilities/internal/types/IsNeverish.cjs +3 -0
- package/__cjs/utilities/internal/types/IsNeverish.cjs.map +1 -0
- package/__cjs/utilities/internal/types/IsNeverish.d.cts +4 -0
- package/__cjs/utilities/internal/types/StreamInfoTrie.d.cts +2 -0
- package/__cjs/utilities/internal/valueToObjectRepresentation.cjs +1 -1
- package/__cjs/utilities/policies/pagination.cjs.map +1 -1
- package/__cjs/utilities/policies/pagination.d.cts +1 -1
- package/__cjs/utilities/subscriptions/relay/index.cjs +1 -0
- package/__cjs/utilities/subscriptions/relay/index.cjs.map +1 -1
- package/__cjs/version.cjs +1 -1
- package/__cjs/version.cjs.map +1 -1
- package/cache/core/Scalar.d.ts +19 -0
- package/cache/core/Scalar.js +32 -0
- package/cache/core/Scalar.js.map +1 -0
- package/cache/core/cache.d.ts +89 -6
- package/cache/core/cache.js +33 -2
- package/cache/core/cache.js.map +1 -1
- package/cache/core/types/Cache.d.ts +25 -0
- package/cache/core/types/Cache.js.map +1 -1
- package/cache/index.d.ts +3 -2
- package/cache/index.js +1 -0
- package/cache/index.js.map +1 -1
- package/cache/inmemory/entityStore.d.ts +3 -0
- package/cache/inmemory/entityStore.js +49 -6
- package/cache/inmemory/entityStore.js.map +1 -1
- package/cache/inmemory/helpers.d.ts +9 -1
- package/cache/inmemory/inMemoryCache.d.ts +44 -5
- package/cache/inmemory/inMemoryCache.js +84 -5
- package/cache/inmemory/inMemoryCache.js.map +1 -1
- package/cache/inmemory/key-extractor.js +1 -1
- package/cache/inmemory/policies.d.ts +4 -1
- package/cache/inmemory/policies.js +35 -6
- package/cache/inmemory/policies.js.map +1 -1
- package/cache/inmemory/readFromStore.d.ts +11 -2
- package/cache/inmemory/readFromStore.js +486 -49
- package/cache/inmemory/readFromStore.js.map +1 -1
- package/cache/inmemory/types.d.ts +30 -5
- package/cache/inmemory/types.js.map +1 -1
- package/cache/inmemory/writeToStore.js +7 -7
- package/cache/inmemory/writeToStore.js.map +1 -1
- package/core/ApolloClient.d.ts +44 -10
- package/core/ApolloClient.js +37 -38
- package/core/ApolloClient.js.map +1 -1
- package/core/ObservableQuery.d.ts +16 -8
- package/core/ObservableQuery.js +225 -77
- package/core/ObservableQuery.js.map +1 -1
- package/core/QueryInfo.d.ts +17 -22
- package/core/QueryInfo.js +174 -190
- package/core/QueryInfo.js.map +1 -1
- package/core/QueryManager.d.ts +1 -3
- package/core/QueryManager.js +89 -60
- package/core/QueryManager.js.map +1 -1
- package/core/RefetchEventManager.js +3 -3
- package/core/dataStateErrorCache.d.ts +3 -0
- package/core/dataStateErrorCache.js +9 -0
- package/core/dataStateErrorCache.js.map +1 -0
- package/core/index.d.ts +4 -3
- package/core/index.js +1 -1
- package/core/index.js.map +1 -1
- package/core/types.d.ts +10 -3
- package/core/types.js.map +1 -1
- package/incremental/GraphQLCodegenIncremental.d.ts +55 -0
- package/incremental/GraphQLCodegenIncremental.js +2 -0
- package/incremental/GraphQLCodegenIncremental.js.map +1 -0
- package/incremental/handlers/defer20220824.d.ts +2 -4
- package/incremental/handlers/defer20220824.js.map +1 -1
- package/incremental/handlers/graphql17Alpha9.d.ts +29 -6
- package/incremental/handlers/graphql17Alpha9.js +48 -17
- package/incremental/handlers/graphql17Alpha9.js.map +1 -1
- package/incremental/handlers/notImplemented.js +1 -1
- package/incremental/index.d.ts +1 -0
- package/incremental/index.js.map +1 -1
- package/incremental/internal/types.d.ts +17 -0
- package/incremental/internal/types.js +2 -0
- package/incremental/internal/types.js.map +1 -0
- package/incremental/types.d.ts +55 -4
- package/incremental/types.js.map +1 -1
- package/invariantErrorCodes.js +167 -112
- package/link/core/ApolloLink.js +3 -3
- package/link/http/checkFetcher.js +1 -1
- package/link/http/parseAndCheckHttpResponse.js +2 -2
- package/link/http/parseAndCheckHttpResponse.js.map +1 -1
- package/link/persisted-queries/index.js +2 -2
- package/link/ws/index.js +1 -1
- package/local-state/LocalState.d.ts +1 -1
- package/local-state/LocalState.js +11 -11
- package/local-state/LocalState.js.map +1 -1
- package/masking/internal/types.d.ts +1 -2
- package/masking/internal/types.js.map +1 -1
- package/masking/maskDefinition.js +2 -2
- package/masking/maskFragment.js +2 -2
- package/masking/maskOperation.js +1 -1
- package/masking/utils.js +3 -3
- package/package.json +1 -1
- package/react/context/ApolloContext.js +1 -1
- package/react/context/ApolloProvider.js +1 -1
- package/react/hooks/internal/validateSuspenseHookOptions.js +2 -2
- package/react/hooks/useApolloClient.js +1 -1
- package/react/hooks/useBackgroundQuery.d.ts +100 -47
- package/react/hooks/useBackgroundQuery.js.map +1 -1
- package/react/hooks/useFragment.d.ts +0 -1
- package/react/hooks/useFragment.js.map +1 -1
- package/react/hooks/useLazyQuery.d.ts +40 -34
- package/react/hooks/useLazyQuery.js +2 -2
- package/react/hooks/useLazyQuery.js.map +1 -1
- package/react/hooks/useLoadableQuery.d.ts +23 -15
- package/react/hooks/useLoadableQuery.js +2 -2
- package/react/hooks/useLoadableQuery.js.map +1 -1
- package/react/hooks/useMutation.d.ts +10 -7
- package/react/hooks/useMutation.js.map +1 -1
- package/react/hooks/useQuery.d.ts +74 -32
- package/react/hooks/useQuery.js.map +1 -1
- package/react/hooks/useQueryRefHandlers.js.map +1 -1
- package/react/hooks/useSubscription.d.ts +7 -4
- package/react/hooks/useSubscription.js +7 -3
- package/react/hooks/useSubscription.js.map +1 -1
- package/react/hooks/useSuspenseFragment.d.ts +1 -1
- package/react/hooks/useSuspenseFragment.js.map +1 -1
- package/react/hooks/useSuspenseQuery.d.ts +83 -34
- package/react/hooks/useSuspenseQuery.js.map +1 -1
- package/react/hooks/useSyncExternalStore.js +1 -1
- package/react/hooks-compiled/internal/validateSuspenseHookOptions.js +2 -2
- package/react/hooks-compiled/useApolloClient.js +1 -1
- package/react/hooks-compiled/useBackgroundQuery.d.ts +100 -47
- package/react/hooks-compiled/useBackgroundQuery.js.map +1 -1
- package/react/hooks-compiled/useFragment.d.ts +0 -1
- package/react/hooks-compiled/useFragment.js.map +1 -1
- package/react/hooks-compiled/useLazyQuery.d.ts +40 -34
- package/react/hooks-compiled/useLazyQuery.js +2 -2
- package/react/hooks-compiled/useLazyQuery.js.map +1 -1
- package/react/hooks-compiled/useLoadableQuery.d.ts +23 -15
- package/react/hooks-compiled/useLoadableQuery.js +2 -2
- package/react/hooks-compiled/useLoadableQuery.js.map +1 -1
- package/react/hooks-compiled/useMutation.d.ts +10 -7
- package/react/hooks-compiled/useMutation.js.map +1 -1
- package/react/hooks-compiled/useQuery.d.ts +74 -32
- package/react/hooks-compiled/useQuery.js.map +1 -1
- package/react/hooks-compiled/useQueryRefHandlers.js.map +1 -1
- package/react/hooks-compiled/useSubscription.d.ts +7 -4
- package/react/hooks-compiled/useSubscription.js +107 -93
- package/react/hooks-compiled/useSubscription.js.map +1 -1
- package/react/hooks-compiled/useSuspenseFragment.d.ts +1 -1
- package/react/hooks-compiled/useSuspenseFragment.js.map +1 -1
- package/react/hooks-compiled/useSuspenseQuery.d.ts +83 -34
- package/react/hooks-compiled/useSuspenseQuery.js.map +1 -1
- package/react/hooks-compiled/useSyncExternalStore.js +1 -1
- package/react/internal/cache/QueryReference.js +1 -1
- package/react/internal/cache/QueryReference.js.map +1 -1
- package/react/internal/types.d.ts +15 -4
- package/react/internal/types.js.map +1 -1
- package/react/query-preloader/createQueryPreloader.d.ts +20 -5
- package/react/query-preloader/createQueryPreloader.js.map +1 -1
- package/react/ssr/prerenderStatic.js +2 -2
- package/testing/core/mocking/mockLink.d.ts +1 -2
- package/testing/core/mocking/mockLink.js +25 -5
- package/testing/core/mocking/mockLink.js.map +1 -1
- package/utilities/caching/sizes.d.ts +39 -1
- package/utilities/caching/sizes.js.map +1 -1
- package/utilities/graphql/DocumentTransform.js +1 -1
- package/utilities/index.d.ts +1 -0
- package/utilities/index.js.map +1 -1
- package/utilities/internal/StreamArrayState.d.ts +12 -0
- package/utilities/internal/StreamArrayState.js +23 -0
- package/utilities/internal/StreamArrayState.js.map +1 -0
- package/utilities/internal/addDeferFragmentLabels.d.ts +3 -0
- package/utilities/internal/addDeferFragmentLabels.js +30 -0
- package/utilities/internal/addDeferFragmentLabels.js.map +1 -0
- package/utilities/internal/capitalize.d.ts +7 -0
- package/utilities/internal/capitalize.js +9 -0
- package/utilities/internal/capitalize.js.map +1 -0
- package/utilities/internal/coerceScalarFieldsToParsed.d.ts +9 -0
- package/utilities/internal/coerceScalarFieldsToParsed.js +66 -0
- package/utilities/internal/coerceScalarFieldsToParsed.js.map +1 -0
- package/utilities/internal/constants.d.ts +19 -0
- package/utilities/internal/constants.js +19 -0
- package/utilities/internal/constants.js.map +1 -1
- package/utilities/internal/getDirectiveArgValue.d.ts +9 -0
- package/utilities/internal/getDirectiveArgValue.js +16 -0
- package/utilities/internal/getDirectiveArgValue.js.map +1 -0
- package/utilities/internal/getFragmentDefinition.js +3 -3
- package/utilities/internal/getFragmentFromSelection.js +2 -2
- package/utilities/internal/getFragmentFromSelection.js.map +1 -1
- package/utilities/internal/getFragmentQueryDocument.js +2 -2
- package/utilities/internal/getMainDefinition.js +1 -1
- package/utilities/internal/getMemoryInternals.d.ts +4 -0
- package/utilities/internal/getMemoryInternals.js +6 -0
- package/utilities/internal/getMemoryInternals.js.map +1 -1
- package/utilities/internal/getQueryDefinition.js +1 -1
- package/utilities/internal/getUnwrappedType.d.ts +8 -0
- package/utilities/internal/getUnwrappedType.js +17 -0
- package/utilities/internal/getUnwrappedType.js.map +1 -0
- package/utilities/internal/index.d.ts +16 -2
- package/utilities/internal/index.js +12 -1
- package/utilities/internal/index.js.map +1 -1
- package/utilities/internal/isDeferredFragment.d.ts +9 -0
- package/utilities/internal/isDeferredFragment.js +35 -0
- package/utilities/internal/isDeferredFragment.js.map +1 -0
- package/utilities/internal/isStreamField.d.ts +9 -0
- package/utilities/internal/isStreamField.js +34 -0
- package/utilities/internal/isStreamField.js.map +1 -0
- package/utilities/internal/isTypenameField.d.ts +3 -0
- package/utilities/internal/isTypenameField.js +4 -0
- package/utilities/internal/isTypenameField.js.map +1 -0
- package/utilities/internal/makeStreamInfoTrie.d.ts +8 -0
- package/utilities/internal/makeStreamInfoTrie.js +14 -0
- package/utilities/internal/makeStreamInfoTrie.js.map +1 -0
- package/utilities/internal/removeDirectivesFromDocument.js +1 -1
- package/utilities/internal/shouldInclude.js +4 -4
- package/utilities/internal/toDiffWithDataState.d.ts +8 -0
- package/utilities/internal/toDiffWithDataState.js +17 -0
- package/utilities/internal/toDiffWithDataState.js.map +1 -0
- package/utilities/internal/types/DeferInfo.d.ts +10 -0
- package/utilities/internal/types/DeferInfo.js +2 -0
- package/utilities/internal/types/DeferInfo.js.map +1 -0
- package/utilities/internal/types/Exact.d.ts +2 -0
- package/utilities/internal/types/Exact.js +2 -0
- package/utilities/internal/types/Exact.js.map +1 -0
- package/utilities/internal/types/IsLooselyEqual.d.ts +10 -0
- package/utilities/internal/types/IsLooselyEqual.js +2 -0
- package/utilities/internal/types/IsLooselyEqual.js.map +1 -0
- package/utilities/internal/types/IsNeverish.d.ts +4 -0
- package/utilities/internal/types/IsNeverish.js +2 -0
- package/utilities/internal/types/IsNeverish.js.map +1 -0
- package/utilities/internal/types/StreamInfoTrie.d.ts +2 -0
- package/utilities/internal/types/StreamInfoTrie.js.map +1 -1
- package/utilities/internal/valueToObjectRepresentation.js +1 -1
- package/utilities/policies/pagination.d.ts +1 -1
- package/utilities/policies/pagination.js.map +1 -1
- package/utilities/subscriptions/relay/index.js +1 -0
- package/utilities/subscriptions/relay/index.js.map +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
- package/__cjs/utilities/internal/types/NoInfer.cjs.map +0 -1
- package/__cjs/utilities/internal/types/NoInfer.d.cts +0 -35
- package/utilities/internal/types/NoInfer.d.ts +0 -35
- package/utilities/internal/types/NoInfer.js +0 -2
- package/utilities/internal/types/NoInfer.js.map +0 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { equal } from "@wry/equality";
|
|
2
|
+
import { Trie } from "@wry/trie";
|
|
1
3
|
import { Kind } from "graphql";
|
|
2
4
|
import { wrap } from "optimism";
|
|
3
5
|
import { addTypenameToDocument, cacheSizes, canonicalStringify, isReference, } from "@apollo/client/utilities";
|
|
4
6
|
import { __DEV__ } from "@apollo/client/utilities/environment";
|
|
5
|
-
import { DeepMerger, getDefaultValues, getFragmentFromSelection, getMainDefinition, getQueryDefinition, isArray, isField, isNonNullObject, makeReference, maybeDeepFreeze, mergeDeepArray, resultKeyNameFromField, shouldInclude, } from "@apollo/client/utilities/internal";
|
|
7
|
+
import { compact, DeepMerger, getDefaultValues, getDirectiveArgValue, getFragmentFromSelection, getMainDefinition, getQueryDefinition, handleIncrementalSymbol, isArray, isDeferredFragment, isField, isNonNullObject, isStreamField, makeReference, maybeDeepFreeze, mergeDeepArray, resultKeyNameFromField, shouldInclude, } from "@apollo/client/utilities/internal";
|
|
6
8
|
import { invariant, newInvariantError, } from "@apollo/client/utilities/invariant";
|
|
7
9
|
import { MissingFieldError } from "../core/types/common.js";
|
|
8
10
|
import { maybeDependOnExistenceOfEntity, supportsResultCaching, } from "./entityStore.js";
|
|
@@ -15,8 +17,11 @@ export class StoreReader {
|
|
|
15
17
|
executeSelectionSet;
|
|
16
18
|
// cached version of executeSubSelectedArray
|
|
17
19
|
executeSubSelectedArray;
|
|
20
|
+
prunePartialStreamArray;
|
|
21
|
+
prunePartialBoundaries;
|
|
18
22
|
config;
|
|
19
23
|
knownResults = new WeakMap();
|
|
24
|
+
keyMaker = new Trie();
|
|
20
25
|
constructor(config) {
|
|
21
26
|
this.config = config;
|
|
22
27
|
// memoized functions in this class will be "garbage-collected"
|
|
@@ -59,47 +64,124 @@ export class StoreReader {
|
|
|
59
64
|
}
|
|
60
65
|
},
|
|
61
66
|
});
|
|
67
|
+
this.prunePartialBoundaries = wrap((options) => this.prunePartialBoundariesImpl(options), {
|
|
68
|
+
max: cacheSizes["inMemoryCache.prunePartialBoundaries"] ||
|
|
69
|
+
20000 /* defaultCacheSizes["inMemoryCache.prunePartialBoundaries"] */,
|
|
70
|
+
makeCacheKey: ({ boundaries, context, selectionSet }) => {
|
|
71
|
+
if (supportsResultCaching(context.store)) {
|
|
72
|
+
return this.keyMaker.lookup(selectionSet, boundaries, context.streamInfo, context.deferInfo);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
this.prunePartialStreamArray = wrap((options) => {
|
|
77
|
+
const { field, context, path } = options;
|
|
78
|
+
if (isStreamField(field, context.variables)) {
|
|
79
|
+
context.streamInfo?.lookupArray(path).state.depend();
|
|
80
|
+
}
|
|
81
|
+
return this.prunePartialStreamArrayImpl(options);
|
|
82
|
+
}, {
|
|
83
|
+
max: cacheSizes["inMemoryCache.prunePartialStreamArray"] ||
|
|
84
|
+
20000 /* defaultCacheSizes["inMemoryCache.prunePartialStreamArray"] */,
|
|
85
|
+
makeCacheKey: ({ field, context, boundaries }) => {
|
|
86
|
+
if (supportsResultCaching(context.store)) {
|
|
87
|
+
return this.keyMaker.lookup(field, boundaries, context.streamInfo, context.deferInfo);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
});
|
|
62
91
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
* identify if any data was missing from the store.
|
|
66
|
-
*/
|
|
67
|
-
diffQueryAgainstStore({ store, query, rootId = "ROOT_QUERY", variables, returnPartialData = true, }) {
|
|
92
|
+
diffQueryAgainstStore({ store, query, rootId = "ROOT_QUERY", variables, returnPartialData = true, ...options }) {
|
|
93
|
+
const returnIncremental = Object.hasOwn(options, handleIncrementalSymbol);
|
|
68
94
|
const policies = this.config.cache.policies;
|
|
69
|
-
variables =
|
|
70
|
-
...getDefaultValues(getQueryDefinition(query)),
|
|
71
|
-
...variables,
|
|
72
|
-
};
|
|
95
|
+
variables = compact(getDefaultValues(getQueryDefinition(query)), variables);
|
|
73
96
|
const rootRef = makeReference(rootId);
|
|
74
|
-
const
|
|
97
|
+
const context = {
|
|
98
|
+
store,
|
|
99
|
+
query,
|
|
100
|
+
policies,
|
|
101
|
+
variables,
|
|
102
|
+
varString: canonicalStringify(variables),
|
|
103
|
+
...extractFragmentContext(query, this.config.fragments),
|
|
104
|
+
...options[handleIncrementalSymbol],
|
|
105
|
+
};
|
|
106
|
+
let execResult = this.executeSelectionSet({
|
|
75
107
|
selectionSet: getMainDefinition(query).selectionSet,
|
|
76
108
|
objectOrReference: rootRef,
|
|
77
109
|
enclosingRef: rootRef,
|
|
78
|
-
context
|
|
79
|
-
store,
|
|
80
|
-
query,
|
|
81
|
-
policies,
|
|
82
|
-
variables,
|
|
83
|
-
varString: canonicalStringify(variables),
|
|
84
|
-
...extractFragmentContext(query, this.config.fragments),
|
|
85
|
-
},
|
|
110
|
+
context,
|
|
86
111
|
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
112
|
+
// Since executeSelectionSet doesn't know about returnPartialData, we need
|
|
113
|
+
// to perform a 2nd pass over the result to prune any fields inside
|
|
114
|
+
// partial defer boundaries. The "deferPartial" data state tells us that the
|
|
115
|
+
// only part of the result that contributed to its partiality is data inside
|
|
116
|
+
// a defer boundary.
|
|
117
|
+
if (returnIncremental && shouldPrune(execResult, context)) {
|
|
118
|
+
const pruned = this.prunePartialBoundaries({
|
|
119
|
+
selectionSet: getMainDefinition(query).selectionSet,
|
|
120
|
+
data: execResult.result,
|
|
121
|
+
boundaries: execResult.partialBoundaries,
|
|
122
|
+
context,
|
|
123
|
+
path: [],
|
|
124
|
+
});
|
|
125
|
+
const changed = execResult.result !== pruned.result;
|
|
126
|
+
// It's possible that pruning didn't actually change the result which can
|
|
127
|
+
// happen if a defer boundary is misclassified as "deferPartial" instead
|
|
128
|
+
// of "streaming" (sibling defer boundaries with overlapping selection
|
|
129
|
+
// sets, one of which is complete). In this case, pruning corrects the
|
|
130
|
+
// dataState to streaming instead of leaving it as partial. If we tolerate
|
|
131
|
+
// partial results and pruning changed the result by dropping fields, then
|
|
132
|
+
// we want to keep the original execResult which contains the partial
|
|
133
|
+
// data.
|
|
134
|
+
if (!changed || !returnPartialData) {
|
|
135
|
+
// Omit `missing` property since pruning puts it in a state that doesn't
|
|
136
|
+
// report missing fields.
|
|
137
|
+
execResult = {
|
|
138
|
+
result: pruned.result,
|
|
139
|
+
partialBoundaries: execResult.partialBoundaries,
|
|
140
|
+
dataState: pruned.dataState,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
90
143
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
144
|
+
let { result, dataState, missing } = execResult;
|
|
145
|
+
// Evaluate this condition before we start mucking with dataState for the
|
|
146
|
+
// publicly returned value
|
|
147
|
+
const includeMissing = !!missing &&
|
|
148
|
+
// We don't need to report missing fields inside defer boundaries since
|
|
149
|
+
// the "streaming" dataState tells us that the only missing fields in
|
|
150
|
+
// the object is inside a defer boundary.
|
|
151
|
+
(dataState !== "streaming" || !returnIncremental);
|
|
152
|
+
// If we get all root @defer boundaries with an empty result, report it as
|
|
153
|
+
// empty instead of streaming.
|
|
154
|
+
if (dataState === "streaming" && Object.keys(result).length === 0) {
|
|
155
|
+
dataState = "empty";
|
|
156
|
+
}
|
|
157
|
+
let missingError;
|
|
158
|
+
if (dataState === "deferPartial" ||
|
|
159
|
+
dataState === "streamPartial" ||
|
|
160
|
+
(dataState === "streaming" && !returnIncremental)) {
|
|
161
|
+
dataState = "partial";
|
|
162
|
+
}
|
|
163
|
+
if (dataState === "partial" && !returnPartialData) {
|
|
164
|
+
dataState = "empty";
|
|
165
|
+
}
|
|
166
|
+
const complete = dataState === "complete";
|
|
167
|
+
const keepResult = complete ||
|
|
168
|
+
dataState === "streaming" ||
|
|
169
|
+
(returnPartialData && Object.keys(result).length);
|
|
170
|
+
const diffResult = {
|
|
171
|
+
result: keepResult ? result : null,
|
|
100
172
|
complete,
|
|
101
|
-
missing
|
|
173
|
+
get missing() {
|
|
174
|
+
if (includeMissing) {
|
|
175
|
+
missingError ||= new MissingFieldError(firstMissing(missing), missing, query, variables);
|
|
176
|
+
}
|
|
177
|
+
return missingError;
|
|
178
|
+
},
|
|
102
179
|
};
|
|
180
|
+
if (returnIncremental) {
|
|
181
|
+
diffResult.dataState =
|
|
182
|
+
dataState;
|
|
183
|
+
}
|
|
184
|
+
return diffResult;
|
|
103
185
|
}
|
|
104
186
|
isFresh(result, parent, selectionSet, context) {
|
|
105
187
|
if (supportsResultCaching(context.store) &&
|
|
@@ -118,14 +200,18 @@ export class StoreReader {
|
|
|
118
200
|
!context.store.has(objectOrReference.__ref)) {
|
|
119
201
|
return {
|
|
120
202
|
result: {},
|
|
203
|
+
dataState: "empty",
|
|
121
204
|
missing: `Dangling reference to missing ${objectOrReference.__ref} object`,
|
|
205
|
+
partialBoundaries: new PartialBoundaries(),
|
|
122
206
|
};
|
|
123
207
|
}
|
|
124
208
|
const { variables, policies, store } = context;
|
|
125
209
|
const typename = store.getFieldValue(objectOrReference, "__typename");
|
|
126
210
|
const objectsToMerge = [];
|
|
211
|
+
let dataState;
|
|
127
212
|
let missing;
|
|
128
213
|
const missingMerger = new DeepMerger();
|
|
214
|
+
const partialBoundaries = new PartialBoundaries();
|
|
129
215
|
if (typeof typename === "string" && !policies.rootIdsByTypename[typename]) {
|
|
130
216
|
// Ensure we always include a default value for the __typename
|
|
131
217
|
// field, if we have one. Note that this field can be overridden by other
|
|
@@ -138,7 +224,7 @@ export class StoreReader {
|
|
|
138
224
|
[resultName]: result.missing,
|
|
139
225
|
});
|
|
140
226
|
}
|
|
141
|
-
return result
|
|
227
|
+
return result;
|
|
142
228
|
}
|
|
143
229
|
const workSet = new Set(selectionSet.selections);
|
|
144
230
|
workSet.forEach((selection) => {
|
|
@@ -156,36 +242,75 @@ export class StoreReader {
|
|
|
156
242
|
const resultName = resultKeyNameFromField(selection);
|
|
157
243
|
if (fieldValue === void 0) {
|
|
158
244
|
if (!addTypenameToDocument.added(selection)) {
|
|
245
|
+
const id = isReference(objectOrReference) ? objectOrReference.__ref
|
|
246
|
+
: objectOrReference ? policies.identify(objectOrReference)[0]
|
|
247
|
+
: undefined;
|
|
159
248
|
missing = missingMerger.merge(missing, {
|
|
160
|
-
[resultName]: `Can't find field '${selection.name.value}' on ${
|
|
161
|
-
|
|
162
|
-
:
|
|
249
|
+
[resultName]: `Can't find field '${selection.name.value}' on ${id ?
|
|
250
|
+
`${id} object`
|
|
251
|
+
: `object ${JSON.stringify(objectOrReference || {}, null, 2)}`}`,
|
|
163
252
|
});
|
|
253
|
+
dataState = mergeDataState(dataState, "empty");
|
|
164
254
|
}
|
|
165
255
|
}
|
|
166
256
|
else if (isArray(fieldValue)) {
|
|
167
257
|
if (fieldValue.length > 0) {
|
|
168
|
-
|
|
258
|
+
const execResult = handleMissing(this.executeSubSelectedArray({
|
|
169
259
|
field: selection,
|
|
170
260
|
array: fieldValue,
|
|
171
261
|
enclosingRef,
|
|
172
262
|
context,
|
|
173
263
|
}), resultName);
|
|
264
|
+
fieldValue = execResult.result;
|
|
265
|
+
dataState = mergeDataState(dataState, execResult.dataState);
|
|
266
|
+
partialBoundaries.set(resultName, execResult.partialBoundaries);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
dataState = mergeDataState(dataState, "complete");
|
|
174
270
|
}
|
|
175
271
|
}
|
|
176
272
|
else if (!selection.selectionSet) {
|
|
177
|
-
//
|
|
273
|
+
// Auto-inserted __typename should not affect dataState (see empty
|
|
274
|
+
// @defer boundaries, which must stay "empty" → parent "streaming").
|
|
275
|
+
if (!addTypenameToDocument.added(selection)) {
|
|
276
|
+
dataState = mergeDataState(dataState, "complete");
|
|
277
|
+
}
|
|
178
278
|
}
|
|
179
279
|
else if (fieldValue != null) {
|
|
280
|
+
if (__DEV__) {
|
|
281
|
+
const fieldName = selection.name.value;
|
|
282
|
+
if (typename) {
|
|
283
|
+
const policy = policies["getFieldPolicy"](typename, fieldName);
|
|
284
|
+
if (policy?.scalar) {
|
|
285
|
+
__DEV__ && invariant.warn(116, `${typename}.${fieldName}`, policy.scalar);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
180
289
|
// In this case, because we know the field has a selection set,
|
|
181
290
|
// it must be trying to query a GraphQLObjectType, which is why
|
|
182
291
|
// fieldValue must be != null.
|
|
183
|
-
|
|
292
|
+
const execResult = handleMissing(this.executeSelectionSet({
|
|
184
293
|
selectionSet: selection.selectionSet,
|
|
185
294
|
objectOrReference: fieldValue,
|
|
186
295
|
enclosingRef: isReference(fieldValue) ? fieldValue : enclosingRef,
|
|
187
296
|
context,
|
|
188
297
|
}), resultName);
|
|
298
|
+
fieldValue = execResult.result;
|
|
299
|
+
partialBoundaries.set(resultName, execResult.partialBoundaries);
|
|
300
|
+
// If the object's fields resolved to an "empty" dataState (e.g. no
|
|
301
|
+
// field resolved with a non-undefined value), but the fieldValue
|
|
302
|
+
// object itself is present, this object should be considered
|
|
303
|
+
// partial instead of empty. This also ensures defer boundaries that
|
|
304
|
+
// select this object remain as partial defer boundaries rather than
|
|
305
|
+
// mistakenly get reported as streaming. This is especially necessary
|
|
306
|
+
// when combined with GraphQL Codegen which generates its type and
|
|
307
|
+
// relies on the outer object to be absent when its fields haven't
|
|
308
|
+
// streamed in. Reporting the defer boundary as "streaming" instead of
|
|
309
|
+
// "partial" would otherwise have the potential to cause runtime
|
|
310
|
+
// crashes since the runtime values and types would not line up
|
|
311
|
+
// properly (types expect object to be undefined, but its instead
|
|
312
|
+
// present without its fields)
|
|
313
|
+
dataState = mergeDataState(dataState, execResult.dataState === "empty" ? "partial" : execResult.dataState);
|
|
189
314
|
}
|
|
190
315
|
if (fieldValue !== void 0) {
|
|
191
316
|
objectsToMerge.push({ [resultName]: fieldValue });
|
|
@@ -194,15 +319,60 @@ export class StoreReader {
|
|
|
194
319
|
else {
|
|
195
320
|
const fragment = getFragmentFromSelection(selection, context.lookupFragment);
|
|
196
321
|
if (!fragment && selection.kind === Kind.FRAGMENT_SPREAD) {
|
|
197
|
-
throw newInvariantError(
|
|
322
|
+
throw newInvariantError(117, selection.name.value);
|
|
198
323
|
}
|
|
199
324
|
if (fragment && policies.fragmentMatches(fragment, typename)) {
|
|
200
|
-
|
|
325
|
+
const isDeferBoundary = isDeferredFragment(selection, context.variables);
|
|
326
|
+
// Prior to 4.3, this branch just flattened the fragment's
|
|
327
|
+
// selectionSet into the existing workSet so that it continued
|
|
328
|
+
// iterating as if the fragment didn't exist. The cache is
|
|
329
|
+
// incremental aware as of 4.3 and as such, we need to resolve the
|
|
330
|
+
// per-fragment selection set so that we can properly strip partial
|
|
331
|
+
// defer fragment data when returnPartialData is false. We need to
|
|
332
|
+
// call execSelectionSetImpl directly (non-cached version) so that we
|
|
333
|
+
// scope the dataState correctly for its fields. Using the cached
|
|
334
|
+
// executeSelectionSet can result in cache poisoning when combined
|
|
335
|
+
// with the fragment registry where it might cache either a) an error
|
|
336
|
+
// thrown when a registered fragment references a named fragment that
|
|
337
|
+
// the query is expected to supply and doesn't or b) resolve to the
|
|
338
|
+
// wrong data result when combined with queries that provide different
|
|
339
|
+
// implementations of the same fragment (see inmemory/fragmentRegistry and
|
|
340
|
+
// cache.diff/incremental tests which provide guards against this
|
|
341
|
+
// behavior).
|
|
342
|
+
const execResult = this.execSelectionSetImpl({
|
|
343
|
+
selectionSet: fragment.selectionSet,
|
|
344
|
+
objectOrReference,
|
|
345
|
+
enclosingRef,
|
|
346
|
+
context,
|
|
347
|
+
});
|
|
348
|
+
const { result, dataState: nextDataState } = execResult;
|
|
349
|
+
partialBoundaries.merge(execResult.partialBoundaries);
|
|
350
|
+
if (result !== void 0) {
|
|
351
|
+
objectsToMerge.push(result);
|
|
352
|
+
}
|
|
353
|
+
if (execResult.missing) {
|
|
354
|
+
missing = missingMerger.merge(missing, execResult.missing);
|
|
355
|
+
}
|
|
356
|
+
if (isDeferBoundary &&
|
|
357
|
+
(nextDataState === "partial" || nextDataState === "empty")) {
|
|
358
|
+
partialBoundaries.add(selection);
|
|
359
|
+
}
|
|
360
|
+
dataState = mergeDataState(dataState, isDeferBoundary ?
|
|
361
|
+
nextDataState === "empty" ? "streaming"
|
|
362
|
+
: nextDataState === "partial" ? "deferPartial"
|
|
363
|
+
: nextDataState
|
|
364
|
+
: nextDataState);
|
|
201
365
|
}
|
|
202
366
|
}
|
|
203
367
|
});
|
|
368
|
+
dataState ||= "complete";
|
|
204
369
|
const result = mergeDeepArray(objectsToMerge);
|
|
205
|
-
const finalResult = {
|
|
370
|
+
const finalResult = {
|
|
371
|
+
result,
|
|
372
|
+
missing,
|
|
373
|
+
dataState,
|
|
374
|
+
partialBoundaries,
|
|
375
|
+
};
|
|
206
376
|
const frozen = maybeDeepFreeze(finalResult);
|
|
207
377
|
// Store this result with its selection set so that we can quickly
|
|
208
378
|
// recognize it again in the StoreReader#isFresh method.
|
|
@@ -213,8 +383,11 @@ export class StoreReader {
|
|
|
213
383
|
}
|
|
214
384
|
// Uncached version of executeSubSelectedArray.
|
|
215
385
|
execSubSelectedArrayImpl({ field, array, enclosingRef, context, }) {
|
|
386
|
+
let dataState = "complete";
|
|
216
387
|
let missing;
|
|
217
388
|
let missingMerger = new DeepMerger();
|
|
389
|
+
const partialBoundaries = new PartialBoundaries();
|
|
390
|
+
const isStreamed = isStreamField(field, context.variables);
|
|
218
391
|
function handleMissing(childResult, i) {
|
|
219
392
|
if (childResult.missing) {
|
|
220
393
|
missing = missingMerger.merge(missing, { [i]: childResult.missing });
|
|
@@ -229,23 +402,36 @@ export class StoreReader {
|
|
|
229
402
|
if (item === null) {
|
|
230
403
|
return null;
|
|
231
404
|
}
|
|
405
|
+
let execResult;
|
|
232
406
|
// This is a nested array, recurse
|
|
233
407
|
if (isArray(item)) {
|
|
234
|
-
|
|
408
|
+
execResult = this.executeSubSelectedArray({
|
|
235
409
|
field,
|
|
236
410
|
array: item,
|
|
237
411
|
enclosingRef,
|
|
238
412
|
context,
|
|
239
|
-
})
|
|
413
|
+
});
|
|
240
414
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
return handleMissing(this.executeSelectionSet({
|
|
415
|
+
else if (field.selectionSet) {
|
|
416
|
+
execResult = this.executeSelectionSet({
|
|
244
417
|
selectionSet: field.selectionSet,
|
|
245
418
|
objectOrReference: item,
|
|
246
419
|
enclosingRef: isReference(item) ? item : enclosingRef,
|
|
247
420
|
context,
|
|
248
|
-
})
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
if (execResult) {
|
|
424
|
+
const { dataState: nextDataState } = execResult;
|
|
425
|
+
partialBoundaries.set(i, nextDataState === "partial" ?
|
|
426
|
+
// avoid mutating the execResult partialBoundaries object
|
|
427
|
+
execResult.partialBoundaries.clone().add(field)
|
|
428
|
+
: execResult.partialBoundaries);
|
|
429
|
+
dataState = mergeDataState(dataState, isStreamed ?
|
|
430
|
+
nextDataState === "partial" ?
|
|
431
|
+
"streamPartial"
|
|
432
|
+
: nextDataState
|
|
433
|
+
: nextDataState);
|
|
434
|
+
return handleMissing(execResult, i);
|
|
249
435
|
}
|
|
250
436
|
if (__DEV__) {
|
|
251
437
|
assertSelectionSetForIdValue(context.store, field, item);
|
|
@@ -254,9 +440,162 @@ export class StoreReader {
|
|
|
254
440
|
});
|
|
255
441
|
return {
|
|
256
442
|
result: array,
|
|
443
|
+
dataState,
|
|
257
444
|
missing,
|
|
445
|
+
partialBoundaries,
|
|
258
446
|
};
|
|
259
447
|
}
|
|
448
|
+
prunePartialBoundariesImpl({ boundaries, context, data, path, selectionSet, }) {
|
|
449
|
+
const { variables, lookupFragment, policies } = context;
|
|
450
|
+
if (data == null || !boundaries) {
|
|
451
|
+
return { result: data, dataState: "complete" };
|
|
452
|
+
}
|
|
453
|
+
const merger = new DeepMerger();
|
|
454
|
+
let changed = false;
|
|
455
|
+
let dataState = "complete";
|
|
456
|
+
const result = {};
|
|
457
|
+
// __typename might not be part of the selection set, so preserve it when
|
|
458
|
+
// available, otherwise it gets removed since it's never visited when
|
|
459
|
+
// iterating the selection set.
|
|
460
|
+
if (Object.hasOwn(data, "__typename")) {
|
|
461
|
+
result.__typename = data.__typename;
|
|
462
|
+
}
|
|
463
|
+
const workSet = new Set(selectionSet.selections);
|
|
464
|
+
workSet.forEach((selection) => {
|
|
465
|
+
if (!shouldInclude(selection, variables))
|
|
466
|
+
return;
|
|
467
|
+
if (isField(selection)) {
|
|
468
|
+
const resultName = resultKeyNameFromField(selection);
|
|
469
|
+
if (!Object.hasOwn(data, resultName)) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
const fieldValue = data[resultName];
|
|
473
|
+
if (Array.isArray(fieldValue)) {
|
|
474
|
+
const pruned = this.prunePartialStreamArray({
|
|
475
|
+
field: selection,
|
|
476
|
+
array: fieldValue,
|
|
477
|
+
boundaries: boundaries.getChild(resultName),
|
|
478
|
+
context,
|
|
479
|
+
path: path.concat(resultName),
|
|
480
|
+
});
|
|
481
|
+
changed ||= pruned.result !== fieldValue;
|
|
482
|
+
result[resultName] = pruned.result;
|
|
483
|
+
dataState = mergeDataState(dataState, pruned.dataState);
|
|
484
|
+
}
|
|
485
|
+
else if (!selection.selectionSet) {
|
|
486
|
+
result[resultName] = fieldValue;
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
const pruned = this.prunePartialBoundaries({
|
|
490
|
+
data: fieldValue,
|
|
491
|
+
selectionSet: selection.selectionSet,
|
|
492
|
+
boundaries: boundaries.getChild(resultName),
|
|
493
|
+
context,
|
|
494
|
+
path: path.concat(resultName),
|
|
495
|
+
});
|
|
496
|
+
changed ||= pruned.result !== fieldValue;
|
|
497
|
+
dataState = mergeDataState(dataState, pruned.dataState);
|
|
498
|
+
// A response key can be selected by more than one selection (e.g. a
|
|
499
|
+
// field and an overlapping fragment), so merge their kept fields.
|
|
500
|
+
result[resultName] =
|
|
501
|
+
Object.hasOwn(result, resultName) ?
|
|
502
|
+
merger.merge(result[resultName], pruned.result)
|
|
503
|
+
: pruned.result;
|
|
504
|
+
}
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
// Note: we do NOT set `changed` to true anywhere in this branch of the
|
|
508
|
+
// conditional, despite the fact that we might have encountered a
|
|
509
|
+
// partial @defer boundary. Dropping a fragment does not guarantee keys
|
|
510
|
+
// are actually dropped which can happen when overlapping sibling
|
|
511
|
+
// selections contribute to the construction of the object. The final
|
|
512
|
+
// Object.keys(result).length check actually detects whether keys were
|
|
513
|
+
// dropped or not.
|
|
514
|
+
const fragment = getFragmentFromSelection(selection, lookupFragment);
|
|
515
|
+
let prune = false;
|
|
516
|
+
if (context.deferInfo && isDeferredFragment(selection, variables)) {
|
|
517
|
+
const directive = selection.directives?.find((d) => d.name.value === "defer");
|
|
518
|
+
const label = directive && getDirectiveArgValue(directive, "label", Kind.STRING);
|
|
519
|
+
prune = !!context.deferInfo.peekArray(path.concat(label || []));
|
|
520
|
+
}
|
|
521
|
+
if (fragment && policies.fragmentMatches(fragment, data.__typename)) {
|
|
522
|
+
if (boundaries.has(selection) || prune) {
|
|
523
|
+
dataState = mergeDataState(dataState, "streaming");
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
fragment.selectionSet.selections.forEach(workSet.add, workSet);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
if (Object.keys(result).length !== Object.keys(data).length) {
|
|
531
|
+
changed = true;
|
|
532
|
+
}
|
|
533
|
+
else if (changed && boundaries.hasSelections()) {
|
|
534
|
+
// Overlapping siblings may rebuild the same fields under a new object
|
|
535
|
+
// identity (e.g. changed === true) after a partial @defer is skipped.
|
|
536
|
+
// We perform a deep equality check to verify whether anything was
|
|
537
|
+
// actually dropped by the partial @defer fragment.
|
|
538
|
+
changed = !equal(result, data);
|
|
539
|
+
}
|
|
540
|
+
return { result: changed ? result : data, dataState };
|
|
541
|
+
}
|
|
542
|
+
prunePartialStreamArrayImpl({ field, array, boundaries, context, path, }) {
|
|
543
|
+
if (!boundaries)
|
|
544
|
+
return { result: array, dataState: "complete" };
|
|
545
|
+
let changed = false;
|
|
546
|
+
let dataState = "complete";
|
|
547
|
+
let pruned = [];
|
|
548
|
+
const state = context.streamInfo?.peekArray(path)?.state;
|
|
549
|
+
const length = Math.min(array.length, state?.truncate ? state.streamPosition : Number.MAX_SAFE_INTEGER);
|
|
550
|
+
for (let i = 0; i < length; i++) {
|
|
551
|
+
const item = array[i];
|
|
552
|
+
let prunedResult = {
|
|
553
|
+
result: item,
|
|
554
|
+
dataState: "complete",
|
|
555
|
+
};
|
|
556
|
+
const boundary = boundaries.getChild(i);
|
|
557
|
+
if (boundary?.has(field)) {
|
|
558
|
+
// The presence of streamInfo determines how we truncate partial
|
|
559
|
+
// stream arrays. Stream info is only given to cache.diff during
|
|
560
|
+
// in-flight requests so we want keep items in the array equal to the
|
|
561
|
+
// total that have streamed in (this is represented by streamPosition
|
|
562
|
+
// above). For all other cache reads, partial stream boundaries are
|
|
563
|
+
// pruned back to an empty array.
|
|
564
|
+
if (state) {
|
|
565
|
+
state.truncate = true;
|
|
566
|
+
pruned = pruned.slice(0, state.streamPosition);
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
pruned = [];
|
|
570
|
+
dataState = "complete";
|
|
571
|
+
}
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
574
|
+
if (Array.isArray(item)) {
|
|
575
|
+
prunedResult = this.prunePartialStreamArray({
|
|
576
|
+
field,
|
|
577
|
+
array: item,
|
|
578
|
+
boundaries: boundaries.getChild(i),
|
|
579
|
+
context,
|
|
580
|
+
path: path.concat(i),
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
else if (field.selectionSet) {
|
|
584
|
+
prunedResult = this.prunePartialBoundaries({
|
|
585
|
+
data: item,
|
|
586
|
+
selectionSet: field.selectionSet,
|
|
587
|
+
boundaries: boundaries.getChild(i),
|
|
588
|
+
context,
|
|
589
|
+
path: path.concat(i),
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
pruned.push(prunedResult.result);
|
|
593
|
+
changed ||= prunedResult.result !== item;
|
|
594
|
+
dataState = mergeDataState(dataState, prunedResult.dataState);
|
|
595
|
+
}
|
|
596
|
+
changed ||= pruned.length !== array.length;
|
|
597
|
+
return { result: changed ? pruned : array, dataState };
|
|
598
|
+
}
|
|
260
599
|
}
|
|
261
600
|
function firstMissing(tree) {
|
|
262
601
|
try {
|
|
@@ -277,7 +616,7 @@ function assertSelectionSetForIdValue(store, field, fieldValue) {
|
|
|
277
616
|
if (isNonNullObject(value)) {
|
|
278
617
|
invariant(
|
|
279
618
|
!isReference(value),
|
|
280
|
-
|
|
619
|
+
118,
|
|
281
620
|
getTypenameFromStoreObject(store, value),
|
|
282
621
|
field.name.value
|
|
283
622
|
);
|
|
@@ -286,4 +625,102 @@ function assertSelectionSetForIdValue(store, field, fieldValue) {
|
|
|
286
625
|
});
|
|
287
626
|
}
|
|
288
627
|
}
|
|
628
|
+
// We deliberately leave `returnPartialData` out of `executeSelectionSet`'s
|
|
629
|
+
// cache key. `isFresh` runs during writes and cannot provide a reliable value
|
|
630
|
+
// for this option, so including it would prevent a reliable cache hit.
|
|
631
|
+
//
|
|
632
|
+
// When `returnPartialData` is false, `diffQueryAgainstStore` prunes data from
|
|
633
|
+
// partial @defer boundaries after reading the cached result. `PartialBoundaries`
|
|
634
|
+
// records the selection paths needed for that pass, including empty nodes along
|
|
635
|
+
// a path. Overlapping non-deferred selections must still be rebuilt so fields
|
|
636
|
+
// contributed only by a partial deferred sibling are removed. The prune pass
|
|
637
|
+
// can then skip unrelated result branches.
|
|
638
|
+
class PartialBoundaries {
|
|
639
|
+
selections = new Set();
|
|
640
|
+
children = new Map();
|
|
641
|
+
add(selection) {
|
|
642
|
+
this.selections.add(selection);
|
|
643
|
+
return this;
|
|
644
|
+
}
|
|
645
|
+
has(selection) {
|
|
646
|
+
return this.selections.has(selection);
|
|
647
|
+
}
|
|
648
|
+
hasSelections() {
|
|
649
|
+
return this.selections.size > 0;
|
|
650
|
+
}
|
|
651
|
+
getChild(key) {
|
|
652
|
+
return this.children.get(key);
|
|
653
|
+
}
|
|
654
|
+
clone() {
|
|
655
|
+
return new PartialBoundaries().merge(this);
|
|
656
|
+
}
|
|
657
|
+
set(key, boundary) {
|
|
658
|
+
const child = this.getChild(key);
|
|
659
|
+
this.children.set(key,
|
|
660
|
+
// Create a new PartialBoundaries instance to avoid mutating any cached
|
|
661
|
+
// execResult partialBoundaries objects
|
|
662
|
+
child ? child.clone().merge(boundary) : boundary);
|
|
663
|
+
}
|
|
664
|
+
merge(boundaries) {
|
|
665
|
+
boundaries.selections.forEach((selection) => this.add(selection));
|
|
666
|
+
boundaries.children.forEach((child, key) => this.set(key, child));
|
|
667
|
+
return this;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
function shouldPrune({ dataState }, context) {
|
|
671
|
+
if (dataState === "deferPartial" || dataState === "streamPartial") {
|
|
672
|
+
return true;
|
|
673
|
+
}
|
|
674
|
+
if (dataState === "complete" || dataState === "streaming") {
|
|
675
|
+
return !!(
|
|
676
|
+
// If the last cache write repaired a partial @stream array to a
|
|
677
|
+
// complete array, the stream array might contain stale entries after
|
|
678
|
+
// the last written value. We only want to deliver the results up to
|
|
679
|
+
// the index the network wrote so we need to prune it too.
|
|
680
|
+
(context.streamInfo ||
|
|
681
|
+
// The network hasn't delivered these @defer boundaries yet, so prune
|
|
682
|
+
// the (possibly complete) cached data sitting at them.
|
|
683
|
+
context.deferInfo));
|
|
684
|
+
}
|
|
685
|
+
return false;
|
|
686
|
+
}
|
|
687
|
+
// Describes the data state transitions that change the running state when it's
|
|
688
|
+
// combined with the next data state. Omitted object values represent
|
|
689
|
+
// "impossible" merges where the data state should remain the same.
|
|
690
|
+
const DATA_STATE_MERGES = {
|
|
691
|
+
empty: {
|
|
692
|
+
complete: "partial",
|
|
693
|
+
deferPartial: "partial",
|
|
694
|
+
streaming: "partial",
|
|
695
|
+
streamPartial: "partial",
|
|
696
|
+
},
|
|
697
|
+
deferPartial: {
|
|
698
|
+
empty: "partial",
|
|
699
|
+
},
|
|
700
|
+
streamPartial: {
|
|
701
|
+
deferPartial: "deferPartial",
|
|
702
|
+
empty: "partial",
|
|
703
|
+
},
|
|
704
|
+
streaming: {
|
|
705
|
+
deferPartial: "deferPartial",
|
|
706
|
+
empty: "partial",
|
|
707
|
+
streamPartial: "streamPartial",
|
|
708
|
+
},
|
|
709
|
+
complete: {
|
|
710
|
+
deferPartial: "deferPartial",
|
|
711
|
+
streaming: "streaming",
|
|
712
|
+
streamPartial: "streamPartial",
|
|
713
|
+
empty: "partial",
|
|
714
|
+
},
|
|
715
|
+
partial: {},
|
|
716
|
+
};
|
|
717
|
+
function mergeDataState(current, next) {
|
|
718
|
+
if (next === "partial") {
|
|
719
|
+
return "partial";
|
|
720
|
+
}
|
|
721
|
+
if (!current || current === next) {
|
|
722
|
+
return next;
|
|
723
|
+
}
|
|
724
|
+
return DATA_STATE_MERGES[current][next] || current;
|
|
725
|
+
}
|
|
289
726
|
//# sourceMappingURL=readFromStore.js.map
|