@apollo/client 3.8.7 → 3.8.8
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/.changeset/README.md +8 -0
- package/.changeset/config.json +14 -0
- package/CHANGELOG.md +3357 -0
- package/apollo-client.cjs +314 -316
- package/apollo-client.cjs.map +1 -1
- package/apollo-client.min.cjs +1 -1
- package/cache/cache.cjs +133 -152
- package/cache/cache.cjs.map +1 -1
- package/cache/cache.cjs.native.js +133 -152
- package/cache/core/cache.d.ts +10 -0
- package/cache/core/cache.js +17 -5
- package/cache/core/cache.js.map +1 -1
- package/cache/core/types/Cache.d.ts +1 -1
- package/cache/core/types/Cache.js.map +1 -1
- package/cache/core/types/DataProxy.d.ts +92 -0
- package/cache/core/types/common.js +4 -1
- package/cache/core/types/common.js.map +1 -1
- package/cache/inmemory/entityStore.d.ts +1 -1
- package/cache/inmemory/entityStore.js +190 -29
- package/cache/inmemory/entityStore.js.map +1 -1
- package/cache/inmemory/fixPolyfills.js +9 -0
- package/cache/inmemory/fixPolyfills.js.map +1 -1
- package/cache/inmemory/fixPolyfills.native.js +12 -0
- package/cache/inmemory/fixPolyfills.native.js.map +1 -1
- package/cache/inmemory/fragmentRegistry.js +23 -12
- package/cache/inmemory/fragmentRegistry.js.map +1 -1
- package/cache/inmemory/helpers.js +20 -11
- package/cache/inmemory/helpers.js.map +1 -1
- package/cache/inmemory/inMemoryCache.js +161 -8
- package/cache/inmemory/inMemoryCache.js.map +1 -1
- package/cache/inmemory/key-extractor.js +72 -4
- package/cache/inmemory/key-extractor.js.map +1 -1
- package/cache/inmemory/object-canon.js +91 -3
- package/cache/inmemory/object-canon.js.map +1 -1
- package/cache/inmemory/policies.js +193 -43
- package/cache/inmemory/policies.js.map +1 -1
- package/cache/inmemory/reactiveVars.js +20 -2
- package/cache/inmemory/reactiveVars.js.map +1 -1
- package/cache/inmemory/readFromStore.d.ts +4 -0
- package/cache/inmemory/readFromStore.js +54 -9
- package/cache/inmemory/readFromStore.js.map +1 -1
- package/cache/inmemory/types.d.ts +28 -0
- package/cache/inmemory/types.js.map +1 -1
- package/cache/inmemory/writeToStore.js +152 -25
- package/cache/inmemory/writeToStore.js.map +1 -1
- package/config/jest/setup.js +2 -0
- package/config/jest/setup.js.map +1 -1
- package/core/ApolloClient.d.ts +264 -3
- package/core/ApolloClient.js +235 -7
- package/core/ApolloClient.js.map +1 -1
- package/core/LocalState.d.ts +4 -6
- package/core/LocalState.js +56 -18
- package/core/LocalState.js.map +1 -1
- package/core/ObservableQuery.d.ts +25 -0
- package/core/ObservableQuery.js +239 -30
- package/core/ObservableQuery.js.map +1 -1
- package/core/QueryInfo.d.ts +3 -3
- package/core/QueryInfo.js +116 -13
- package/core/QueryInfo.js.map +1 -1
- package/core/QueryManager.d.ts +4 -0
- package/core/QueryManager.js +229 -33
- package/core/QueryManager.js.map +1 -1
- package/core/core.cjs +112 -103
- package/core/core.cjs.map +1 -1
- package/core/core.cjs.native.js +112 -103
- package/core/equalByQuery.js +20 -1
- package/core/equalByQuery.js.map +1 -1
- package/core/index.d.ts +1 -1
- package/core/index.js +19 -0
- package/core/index.js.map +1 -1
- package/core/networkStatus.d.ts +39 -0
- package/core/networkStatus.js +39 -0
- package/core/networkStatus.js.map +1 -1
- package/core/types.d.ts +9 -0
- package/core/types.js.map +1 -1
- package/core/watchQueryOptions.d.ts +225 -1
- package/core/watchQueryOptions.js.map +1 -1
- package/dev/dev.cjs +5 -111
- package/dev/dev.cjs.map +1 -1
- package/dev/dev.cjs.native.js +5 -111
- package/dev/loadErrorMessageHandler.js.map +1 -1
- package/errors/errors.cjs +1 -1
- package/errors/errors.cjs.map +1 -1
- package/errors/errors.cjs.native.js +1 -1
- package/errors/index.js +14 -1
- package/errors/index.js.map +1 -1
- package/invariantErrorCodes.js +1 -0
- package/link/batch/batch.cjs +2 -2
- package/link/batch/batch.cjs.map +1 -1
- package/link/batch/batch.cjs.native.js +2 -2
- package/link/batch/batchLink.d.ts +21 -0
- package/link/batch/batchLink.js +2 -1
- package/link/batch/batchLink.js.map +1 -1
- package/link/batch/batching.js +24 -1
- package/link/batch/batching.js.map +1 -1
- package/link/batch-http/batch-http.cjs +3 -2
- package/link/batch-http/batch-http.cjs.map +1 -1
- package/link/batch-http/batch-http.cjs.native.js +3 -2
- package/link/batch-http/batchHttpLink.d.ts +4 -0
- package/link/batch-http/batchHttpLink.js +53 -2
- package/link/batch-http/batchHttpLink.js.map +1 -1
- package/link/context/context.cjs.map +1 -1
- package/link/context/index.js +1 -0
- package/link/context/index.js.map +1 -1
- package/link/core/ApolloLink.js +12 -5
- package/link/core/ApolloLink.js.map +1 -1
- package/link/core/core.cjs +5 -5
- package/link/core/core.cjs.map +1 -1
- package/link/core/core.cjs.native.js +5 -5
- package/link/error/error.cjs +1 -1
- package/link/error/error.cjs.map +1 -1
- package/link/error/error.cjs.native.js +1 -1
- package/link/error/index.d.ts +3 -0
- package/link/error/index.js +4 -1
- package/link/error/index.js.map +1 -1
- package/link/http/HttpLink.d.ts +0 -2
- package/link/http/HttpLink.js +1 -1
- package/link/http/HttpLink.js.map +1 -1
- package/link/http/checkFetcher.js.map +1 -1
- package/link/http/createHttpLink.js +23 -1
- package/link/http/createHttpLink.js.map +1 -1
- package/link/http/createSignalIfSupported.d.ts +5 -0
- package/link/http/createSignalIfSupported.js +5 -0
- package/link/http/createSignalIfSupported.js.map +1 -1
- package/link/http/http.cjs +14 -12
- package/link/http/http.cjs.map +1 -1
- package/link/http/http.cjs.native.js +14 -12
- package/link/http/index.js +2 -1
- package/link/http/index.js.map +1 -1
- package/link/http/iterators/async.d.ts +4 -0
- package/link/http/iterators/async.js +4 -0
- package/link/http/iterators/async.js.map +1 -1
- package/link/http/iterators/nodeStream.d.ts +4 -0
- package/link/http/iterators/nodeStream.js +4 -0
- package/link/http/iterators/nodeStream.js.map +1 -1
- package/link/http/iterators/promise.d.ts +4 -0
- package/link/http/iterators/promise.js +4 -0
- package/link/http/iterators/promise.js.map +1 -1
- package/link/http/iterators/reader.d.ts +4 -0
- package/link/http/iterators/reader.js +4 -0
- package/link/http/iterators/reader.js.map +1 -1
- package/link/http/parseAndCheckHttpResponse.js +51 -10
- package/link/http/parseAndCheckHttpResponse.js.map +1 -1
- package/link/http/responseIterator.d.ts +4 -0
- package/link/http/responseIterator.js +6 -0
- package/link/http/responseIterator.js.map +1 -1
- package/link/http/rewriteURIForGET.d.ts +1 -1
- package/link/http/rewriteURIForGET.js +10 -0
- package/link/http/rewriteURIForGET.js.map +1 -1
- package/link/http/selectHttpOptionsAndBody.d.ts +45 -0
- package/link/http/selectHttpOptionsAndBody.js +23 -0
- package/link/http/selectHttpOptionsAndBody.js.map +1 -1
- package/link/http/selectURI.js.map +1 -1
- package/link/http/serializeFetchParameter.js.map +1 -1
- package/link/persisted-queries/index.js +34 -4
- package/link/persisted-queries/index.js.map +1 -1
- package/link/persisted-queries/persisted-queries.cjs +4 -4
- package/link/persisted-queries/persisted-queries.cjs.map +1 -1
- package/link/persisted-queries/persisted-queries.cjs.native.js +4 -4
- package/link/remove-typename/remove-typename.cjs +12 -9
- package/link/remove-typename/remove-typename.cjs.map +1 -1
- package/link/remove-typename/remove-typename.cjs.native.js +12 -9
- package/link/remove-typename/removeTypenameFromVariables.js +12 -9
- package/link/remove-typename/removeTypenameFromVariables.js.map +1 -1
- package/link/retry/delayFunction.d.ts +29 -0
- package/link/retry/delayFunction.js +6 -0
- package/link/retry/delayFunction.js.map +1 -1
- package/link/retry/retry.cjs +5 -5
- package/link/retry/retry.cjs.map +1 -1
- package/link/retry/retry.cjs.native.js +5 -5
- package/link/retry/retryFunction.d.ts +20 -0
- package/link/retry/retryLink.d.ts +6 -0
- package/link/retry/retryLink.js +31 -6
- package/link/retry/retryLink.js.map +1 -1
- package/link/schema/index.d.ts +13 -0
- package/link/schema/index.js +3 -3
- package/link/schema/index.js.map +1 -1
- package/link/schema/schema.cjs +3 -3
- package/link/schema/schema.cjs.map +1 -1
- package/link/schema/schema.cjs.native.js +3 -3
- package/link/subscriptions/index.js +35 -2
- package/link/subscriptions/index.js.map +1 -1
- package/link/subscriptions/subscriptions.cjs +3 -2
- package/link/subscriptions/subscriptions.cjs.map +1 -1
- package/link/subscriptions/subscriptions.cjs.native.js +3 -2
- package/link/utils/createOperation.js.map +1 -1
- package/link/utils/filterOperationVariables.js +4 -0
- package/link/utils/filterOperationVariables.js.map +1 -1
- package/link/utils/toPromise.js.map +1 -1
- package/link/utils/transformOperation.js +3 -2
- package/link/utils/transformOperation.js.map +1 -1
- package/link/utils/utils.cjs +2 -2
- package/link/utils/utils.cjs.map +1 -1
- package/link/utils/utils.cjs.native.js +2 -2
- package/link/utils/validateOperation.js.map +1 -1
- package/link/ws/index.d.ts +12 -0
- package/link/ws/index.js +1 -1
- package/link/ws/index.js.map +1 -1
- package/link/ws/ws.cjs +1 -1
- package/link/ws/ws.cjs.map +1 -1
- package/link/ws/ws.cjs.native.js +1 -1
- package/package.json +49 -38
- package/react/cache/QueryReference.d.ts +6 -1
- package/react/cache/QueryReference.js +26 -1
- package/react/cache/QueryReference.js.map +1 -1
- package/react/cache/SuspenseCache.d.ts +10 -0
- package/react/cache/SuspenseCache.js +1 -1
- package/react/cache/SuspenseCache.js.map +1 -1
- package/react/cache/getSuspenseCache.js.map +1 -1
- package/react/context/ApolloContext.d.ts +5 -0
- package/react/context/ApolloContext.js +10 -3
- package/react/context/ApolloContext.js.map +1 -1
- package/react/context/context.cjs +1 -3
- package/react/context/context.cjs.map +1 -1
- package/react/context/context.cjs.native.js +1 -3
- package/react/hoc/graphql.js.map +1 -1
- package/react/hoc/hoc-utils.js +3 -1
- package/react/hoc/hoc-utils.js.map +1 -1
- package/react/hoc/hoc.cjs +9 -17
- package/react/hoc/hoc.cjs.map +1 -1
- package/react/hoc/hoc.cjs.native.js +9 -17
- package/react/hoc/mutation-hoc.js +9 -4
- package/react/hoc/mutation-hoc.js.map +1 -1
- package/react/hoc/query-hoc.js +10 -4
- package/react/hoc/query-hoc.js.map +1 -1
- package/react/hoc/subscription-hoc.js +10 -4
- package/react/hoc/subscription-hoc.js.map +1 -1
- package/react/hoc/withApollo.js +3 -4
- package/react/hoc/withApollo.js.map +1 -1
- package/react/hooks/hooks.cjs +30 -22
- package/react/hooks/hooks.cjs.map +1 -1
- package/react/hooks/hooks.cjs.native.js +30 -22
- package/react/hooks/internal/__use.js +5 -0
- package/react/hooks/internal/__use.js.map +1 -1
- package/react/hooks/internal/index.js +1 -0
- package/react/hooks/internal/index.js.map +1 -1
- package/react/hooks/internal/useDeepMemo.js.map +1 -1
- package/react/hooks/internal/useIsomorphicLayoutEffect.js +6 -3
- package/react/hooks/internal/useIsomorphicLayoutEffect.js.map +1 -1
- package/react/hooks/useBackgroundQuery.js +6 -0
- package/react/hooks/useBackgroundQuery.js.map +1 -1
- package/react/hooks/useFragment.js +4 -3
- package/react/hooks/useFragment.js.map +1 -1
- package/react/hooks/useLazyQuery.js +13 -4
- package/react/hooks/useLazyQuery.js.map +1 -1
- package/react/hooks/useMutation.js +8 -3
- package/react/hooks/useMutation.js.map +1 -1
- package/react/hooks/useQuery.d.ts +11 -0
- package/react/hooks/useQuery.js +137 -5
- package/react/hooks/useQuery.js.map +1 -1
- package/react/hooks/useReactiveVar.js +5 -0
- package/react/hooks/useReactiveVar.js.map +1 -1
- package/react/hooks/useReadQuery.d.ts +19 -0
- package/react/hooks/useReadQuery.js.map +1 -1
- package/react/hooks/useSubscription.js +5 -0
- package/react/hooks/useSubscription.js.map +1 -1
- package/react/hooks/useSuspenseQuery.js +11 -5
- package/react/hooks/useSuspenseQuery.js.map +1 -1
- package/react/hooks/useSyncExternalStore.js +53 -1
- package/react/hooks/useSyncExternalStore.js.map +1 -1
- package/react/parser/index.js +4 -5
- package/react/parser/index.js.map +1 -1
- package/react/parser/parser.cjs +2 -4
- package/react/parser/parser.cjs.map +1 -1
- package/react/parser/parser.cjs.native.js +2 -4
- package/react/ssr/RenderPromises.js +21 -1
- package/react/ssr/RenderPromises.js.map +1 -1
- package/react/ssr/getDataFromTree.js +18 -3
- package/react/ssr/getDataFromTree.js.map +1 -1
- package/react/ssr/ssr.cjs +6 -4
- package/react/ssr/ssr.cjs.map +1 -1
- package/react/ssr/ssr.cjs.native.js +6 -4
- package/react/types/types.d.ts +66 -0
- package/testing/core/core.cjs +14 -11
- package/testing/core/core.cjs.map +1 -1
- package/testing/core/core.cjs.native.js +14 -11
- package/testing/core/itAsync.d.ts +1 -1
- package/testing/core/itAsync.js.map +1 -1
- package/testing/core/mocking/mockFetch.d.ts +2 -2
- package/testing/core/mocking/mockFetch.js +8 -4
- package/testing/core/mocking/mockFetch.js.map +1 -1
- package/testing/core/mocking/mockLink.js +17 -7
- package/testing/core/mocking/mockLink.js.map +1 -1
- package/testing/core/mocking/mockQueryManager.js +2 -0
- package/testing/core/mocking/mockQueryManager.js.map +1 -1
- package/testing/core/mocking/mockSubscriptionLink.d.ts +1 -1
- package/testing/core/mocking/mockSubscriptionLink.js +1 -1
- package/testing/core/mocking/mockSubscriptionLink.js.map +1 -1
- package/testing/core/mocking/mockWatchQuery.js +1 -1
- package/testing/core/mocking/mockWatchQuery.js.map +1 -1
- package/testing/core/observableToPromise.d.ts +17 -3
- package/testing/core/observableToPromise.js +5 -0
- package/testing/core/observableToPromise.js.map +1 -1
- package/testing/core/subscribeAndCount.js +3 -0
- package/testing/core/subscribeAndCount.js.map +1 -1
- package/testing/core/wait.js +2 -2
- package/testing/core/wait.js.map +1 -1
- package/testing/core/withConsoleSpy.d.ts +3 -0
- package/testing/core/withConsoleSpy.js +7 -1
- package/testing/core/withConsoleSpy.js.map +1 -1
- package/testing/core/wrap.js +2 -0
- package/testing/core/wrap.js.map +1 -1
- package/testing/internal/ObservableStream.js +14 -14
- package/testing/internal/ObservableStream.js.map +1 -1
- package/testing/internal/disposables/spyOnConsole.d.ts +1 -0
- package/testing/internal/disposables/spyOnConsole.js +2 -0
- package/testing/internal/disposables/spyOnConsole.js.map +1 -1
- package/testing/internal/disposables/withCleanup.d.ts +1 -0
- package/testing/internal/disposables/withCleanup.js +3 -0
- package/testing/internal/disposables/withCleanup.js.map +1 -1
- package/testing/internal/profile/Render.d.ts +28 -0
- package/testing/internal/profile/Render.js +12 -1
- package/testing/internal/profile/Render.js.map +1 -1
- package/testing/internal/profile/profile.d.ts +44 -7
- package/testing/internal/profile/profile.js +63 -51
- package/testing/internal/profile/profile.js.map +1 -1
- package/testing/internal/profile/traces.d.ts +4 -0
- package/testing/internal/profile/traces.js +9 -5
- package/testing/internal/profile/traces.js.map +1 -1
- package/testing/matchers/ProfiledComponent.js +27 -22
- package/testing/matchers/ProfiledComponent.js.map +1 -1
- package/testing/matchers/toHaveSuspenseCacheEntryUsing.js.map +1 -1
- package/testing/matchers/toMatchDocument.js.map +1 -1
- package/testing/react/MockedProvider.d.ts +4 -0
- package/testing/react/MockedProvider.js +6 -2
- package/testing/react/MockedProvider.js.map +1 -1
- package/testing/testing.cjs +4 -2
- package/testing/testing.cjs.map +1 -1
- package/testing/testing.cjs.native.js +4 -2
- package/utilities/common/arrays.js +1 -0
- package/utilities/common/arrays.js.map +1 -1
- package/utilities/common/canUse.js +16 -1
- package/utilities/common/canUse.js.map +1 -1
- package/utilities/common/cloneDeep.d.ts +3 -0
- package/utilities/common/cloneDeep.js +5 -0
- package/utilities/common/cloneDeep.js.map +1 -1
- package/utilities/common/compact.d.ts +4 -0
- package/utilities/common/compact.js +4 -0
- package/utilities/common/compact.js.map +1 -1
- package/utilities/common/errorHandling.js +1 -3
- package/utilities/common/errorHandling.js.map +1 -1
- package/utilities/common/incrementalResult.js +3 -0
- package/utilities/common/incrementalResult.js.map +1 -1
- package/utilities/common/makeUniqueId.js +2 -0
- package/utilities/common/makeUniqueId.js.map +1 -1
- package/utilities/common/maybeDeepFreeze.js +3 -0
- package/utilities/common/maybeDeepFreeze.js.map +1 -1
- package/utilities/common/mergeDeep.js +12 -1
- package/utilities/common/mergeDeep.js.map +1 -1
- package/utilities/common/mergeOptions.d.ts +1 -1
- package/utilities/common/mergeOptions.js.map +1 -1
- package/utilities/common/omitDeep.js.map +1 -1
- package/utilities/globals/global.js +7 -1
- package/utilities/globals/global.js.map +1 -1
- package/utilities/globals/globals.cjs +4 -5
- package/utilities/globals/globals.cjs.map +1 -1
- package/utilities/globals/globals.cjs.native.js +4 -5
- package/utilities/globals/index.d.ts +4 -0
- package/utilities/globals/index.js +7 -0
- package/utilities/globals/index.js.map +1 -1
- package/utilities/globals/invariantWrappers.d.ts +40 -0
- package/utilities/globals/invariantWrappers.js +11 -3
- package/utilities/globals/invariantWrappers.js.map +1 -1
- package/utilities/globals/maybe.js.map +1 -1
- package/utilities/graphql/DocumentTransform.js +19 -6
- package/utilities/graphql/DocumentTransform.js.map +1 -1
- package/utilities/graphql/directives.js +3 -0
- package/utilities/graphql/directives.js.map +1 -1
- package/utilities/graphql/fragments.d.ts +25 -0
- package/utilities/graphql/fragments.js +36 -0
- package/utilities/graphql/fragments.js.map +1 -1
- package/utilities/graphql/getFromAST.d.ts +5 -0
- package/utilities/graphql/getFromAST.js +9 -0
- package/utilities/graphql/getFromAST.js.map +1 -1
- package/utilities/graphql/print.js.map +1 -1
- package/utilities/graphql/storeUtils.d.ts +14 -0
- package/utilities/graphql/storeUtils.js +7 -2
- package/utilities/graphql/storeUtils.js.map +1 -1
- package/utilities/graphql/transform.js +106 -7
- package/utilities/graphql/transform.js.map +1 -1
- package/utilities/observables/Concast.d.ts +1 -1
- package/utilities/observables/Concast.js +84 -1
- package/utilities/observables/Concast.js.map +1 -1
- package/utilities/observables/Observable.js +6 -0
- package/utilities/observables/Observable.js.map +1 -1
- package/utilities/observables/asyncMap.js +12 -3
- package/utilities/observables/asyncMap.js.map +1 -1
- package/utilities/observables/iteration.js +3 -0
- package/utilities/observables/iteration.js.map +1 -1
- package/utilities/observables/subclassing.js +14 -0
- package/utilities/observables/subclassing.js.map +1 -1
- package/utilities/policies/pagination.js +47 -3
- package/utilities/policies/pagination.js.map +1 -1
- package/utilities/promises/decoration.js +1 -0
- package/utilities/promises/decoration.js.map +1 -1
- package/utilities/types/DeepOmit.js.map +1 -1
- package/utilities/types/DeepPartial.d.ts +1 -1
- package/utilities/types/DeepPartial.js +4 -0
- package/utilities/types/DeepPartial.js.map +1 -1
- package/utilities/types/IsStrictlyAny.js.map +1 -1
- package/utilities/types/TODO.d.ts +3 -0
- package/utilities/types/TODO.js +2 -0
- package/utilities/types/TODO.js.map +1 -0
- package/utilities/utilities.cjs +31 -27
- package/utilities/utilities.cjs.map +1 -1
- package/utilities/utilities.cjs.native.js +31 -27
- package/version.js +1 -1
- package/cache/core/cache.d.ts.map +0 -1
- package/cache/core/types/Cache.d.ts.map +0 -1
- package/cache/core/types/DataProxy.d.ts.map +0 -1
- package/cache/core/types/common.d.ts.map +0 -1
- package/cache/index.d.ts.map +0 -1
- package/cache/inmemory/entityStore.d.ts.map +0 -1
- package/cache/inmemory/fixPolyfills.d.ts.map +0 -1
- package/cache/inmemory/fixPolyfills.native.d.ts.map +0 -1
- package/cache/inmemory/fragmentRegistry.d.ts.map +0 -1
- package/cache/inmemory/helpers.d.ts.map +0 -1
- package/cache/inmemory/inMemoryCache.d.ts.map +0 -1
- package/cache/inmemory/key-extractor.d.ts.map +0 -1
- package/cache/inmemory/object-canon.d.ts.map +0 -1
- package/cache/inmemory/policies.d.ts.map +0 -1
- package/cache/inmemory/reactiveVars.d.ts.map +0 -1
- package/cache/inmemory/readFromStore.d.ts.map +0 -1
- package/cache/inmemory/types.d.ts.map +0 -1
- package/cache/inmemory/writeToStore.d.ts.map +0 -1
- package/config/jest/setup.d.ts.map +0 -1
- package/core/ApolloClient.d.ts.map +0 -1
- package/core/LocalState.d.ts.map +0 -1
- package/core/ObservableQuery.d.ts.map +0 -1
- package/core/QueryInfo.d.ts.map +0 -1
- package/core/QueryManager.d.ts.map +0 -1
- package/core/equalByQuery.d.ts.map +0 -1
- package/core/index.d.ts.map +0 -1
- package/core/networkStatus.d.ts.map +0 -1
- package/core/types.d.ts.map +0 -1
- package/core/watchQueryOptions.d.ts.map +0 -1
- package/dev/index.d.ts.map +0 -1
- package/dev/loadDevMessages.d.ts.map +0 -1
- package/dev/loadErrorMessageHandler.d.ts.map +0 -1
- package/dev/loadErrorMessages.d.ts.map +0 -1
- package/errors/index.d.ts.map +0 -1
- package/index.d.ts.map +0 -1
- package/invariantErrorCodes.d.ts.map +0 -1
- package/link/batch/batchLink.d.ts.map +0 -1
- package/link/batch/batching.d.ts.map +0 -1
- package/link/batch/index.d.ts.map +0 -1
- package/link/batch-http/batchHttpLink.d.ts.map +0 -1
- package/link/batch-http/index.d.ts.map +0 -1
- package/link/context/index.d.ts.map +0 -1
- package/link/core/ApolloLink.d.ts.map +0 -1
- package/link/core/concat.d.ts.map +0 -1
- package/link/core/empty.d.ts.map +0 -1
- package/link/core/execute.d.ts.map +0 -1
- package/link/core/from.d.ts.map +0 -1
- package/link/core/index.d.ts.map +0 -1
- package/link/core/split.d.ts.map +0 -1
- package/link/core/types.d.ts.map +0 -1
- package/link/error/index.d.ts.map +0 -1
- package/link/http/HttpLink.d.ts.map +0 -1
- package/link/http/checkFetcher.d.ts.map +0 -1
- package/link/http/createHttpLink.d.ts.map +0 -1
- package/link/http/createSignalIfSupported.d.ts.map +0 -1
- package/link/http/index.d.ts.map +0 -1
- package/link/http/iterators/async.d.ts.map +0 -1
- package/link/http/iterators/nodeStream.d.ts.map +0 -1
- package/link/http/iterators/promise.d.ts.map +0 -1
- package/link/http/iterators/reader.d.ts.map +0 -1
- package/link/http/parseAndCheckHttpResponse.d.ts.map +0 -1
- package/link/http/responseIterator.d.ts.map +0 -1
- package/link/http/rewriteURIForGET.d.ts.map +0 -1
- package/link/http/selectHttpOptionsAndBody.d.ts.map +0 -1
- package/link/http/selectURI.d.ts.map +0 -1
- package/link/http/serializeFetchParameter.d.ts.map +0 -1
- package/link/persisted-queries/index.d.ts.map +0 -1
- package/link/remove-typename/index.d.ts.map +0 -1
- package/link/remove-typename/removeTypenameFromVariables.d.ts.map +0 -1
- package/link/retry/delayFunction.d.ts.map +0 -1
- package/link/retry/index.d.ts.map +0 -1
- package/link/retry/retryFunction.d.ts.map +0 -1
- package/link/retry/retryLink.d.ts.map +0 -1
- package/link/schema/index.d.ts.map +0 -1
- package/link/subscriptions/index.d.ts.map +0 -1
- package/link/utils/createOperation.d.ts.map +0 -1
- package/link/utils/filterOperationVariables.d.ts.map +0 -1
- package/link/utils/fromError.d.ts.map +0 -1
- package/link/utils/fromPromise.d.ts.map +0 -1
- package/link/utils/index.d.ts.map +0 -1
- package/link/utils/throwServerError.d.ts.map +0 -1
- package/link/utils/toPromise.d.ts.map +0 -1
- package/link/utils/transformOperation.d.ts.map +0 -1
- package/link/utils/validateOperation.d.ts.map +0 -1
- package/link/ws/index.d.ts.map +0 -1
- package/react/cache/QueryReference.d.ts.map +0 -1
- package/react/cache/SuspenseCache.d.ts.map +0 -1
- package/react/cache/getSuspenseCache.d.ts.map +0 -1
- package/react/cache/index.d.ts.map +0 -1
- package/react/cache/types.d.ts.map +0 -1
- package/react/components/Mutation.d.ts.map +0 -1
- package/react/components/Query.d.ts.map +0 -1
- package/react/components/Subscription.d.ts.map +0 -1
- package/react/components/index.d.ts.map +0 -1
- package/react/components/types.d.ts.map +0 -1
- package/react/context/ApolloConsumer.d.ts.map +0 -1
- package/react/context/ApolloContext.d.ts.map +0 -1
- package/react/context/ApolloProvider.d.ts.map +0 -1
- package/react/context/index.d.ts.map +0 -1
- package/react/hoc/graphql.d.ts.map +0 -1
- package/react/hoc/hoc-utils.d.ts.map +0 -1
- package/react/hoc/index.d.ts.map +0 -1
- package/react/hoc/mutation-hoc.d.ts.map +0 -1
- package/react/hoc/query-hoc.d.ts.map +0 -1
- package/react/hoc/subscription-hoc.d.ts.map +0 -1
- package/react/hoc/types.d.ts.map +0 -1
- package/react/hoc/withApollo.d.ts.map +0 -1
- package/react/hooks/constants.d.ts.map +0 -1
- package/react/hooks/index.d.ts.map +0 -1
- package/react/hooks/internal/__use.d.ts.map +0 -1
- package/react/hooks/internal/index.d.ts.map +0 -1
- package/react/hooks/internal/useDeepMemo.d.ts.map +0 -1
- package/react/hooks/internal/useIsomorphicLayoutEffect.d.ts.map +0 -1
- package/react/hooks/useApolloClient.d.ts.map +0 -1
- package/react/hooks/useBackgroundQuery.d.ts.map +0 -1
- package/react/hooks/useFragment.d.ts.map +0 -1
- package/react/hooks/useLazyQuery.d.ts.map +0 -1
- package/react/hooks/useMutation.d.ts.map +0 -1
- package/react/hooks/useQuery.d.ts.map +0 -1
- package/react/hooks/useReactiveVar.d.ts.map +0 -1
- package/react/hooks/useReadQuery.d.ts.map +0 -1
- package/react/hooks/useSubscription.d.ts.map +0 -1
- package/react/hooks/useSuspenseQuery.d.ts.map +0 -1
- package/react/hooks/useSyncExternalStore.d.ts.map +0 -1
- package/react/index.d.ts.map +0 -1
- package/react/parser/index.d.ts.map +0 -1
- package/react/ssr/RenderPromises.d.ts.map +0 -1
- package/react/ssr/getDataFromTree.d.ts.map +0 -1
- package/react/ssr/index.d.ts.map +0 -1
- package/react/ssr/renderToStringWithData.d.ts.map +0 -1
- package/react/types/types.d.ts.map +0 -1
- package/testing/core/index.d.ts.map +0 -1
- package/testing/core/itAsync.d.ts.map +0 -1
- package/testing/core/mocking/mockClient.d.ts.map +0 -1
- package/testing/core/mocking/mockFetch.d.ts.map +0 -1
- package/testing/core/mocking/mockLink.d.ts.map +0 -1
- package/testing/core/mocking/mockQueryManager.d.ts.map +0 -1
- package/testing/core/mocking/mockSubscriptionLink.d.ts.map +0 -1
- package/testing/core/mocking/mockWatchQuery.d.ts.map +0 -1
- package/testing/core/observableToPromise.d.ts.map +0 -1
- package/testing/core/subscribeAndCount.d.ts.map +0 -1
- package/testing/core/wait.d.ts.map +0 -1
- package/testing/core/withConsoleSpy.d.ts.map +0 -1
- package/testing/core/wrap.d.ts.map +0 -1
- package/testing/index.d.ts.map +0 -1
- package/testing/internal/ObservableStream.d.ts.map +0 -1
- package/testing/internal/disposables/index.d.ts.map +0 -1
- package/testing/internal/disposables/spyOnConsole.d.ts.map +0 -1
- package/testing/internal/disposables/withCleanup.d.ts.map +0 -1
- package/testing/internal/index.d.ts.map +0 -1
- package/testing/internal/profile/Render.d.ts.map +0 -1
- package/testing/internal/profile/index.d.ts.map +0 -1
- package/testing/internal/profile/profile.d.ts.map +0 -1
- package/testing/internal/profile/traces.d.ts.map +0 -1
- package/testing/matchers/ProfiledComponent.d.ts.map +0 -1
- package/testing/matchers/index.d.ts.map +0 -1
- package/testing/matchers/toHaveSuspenseCacheEntryUsing.d.ts.map +0 -1
- package/testing/matchers/toMatchDocument.d.ts.map +0 -1
- package/testing/react/MockedProvider.d.ts.map +0 -1
- package/utilities/common/arrays.d.ts.map +0 -1
- package/utilities/common/canUse.d.ts.map +0 -1
- package/utilities/common/cloneDeep.d.ts.map +0 -1
- package/utilities/common/compact.d.ts.map +0 -1
- package/utilities/common/errorHandling.d.ts.map +0 -1
- package/utilities/common/filterInPlace.d.ts +0 -2
- package/utilities/common/filterInPlace.d.ts.map +0 -1
- package/utilities/common/filterInPlace.js +0 -11
- package/utilities/common/filterInPlace.js.map +0 -1
- package/utilities/common/incrementalResult.d.ts.map +0 -1
- package/utilities/common/makeUniqueId.d.ts.map +0 -1
- package/utilities/common/maybeDeepFreeze.d.ts.map +0 -1
- package/utilities/common/mergeDeep.d.ts.map +0 -1
- package/utilities/common/mergeOptions.d.ts.map +0 -1
- package/utilities/common/objects.d.ts.map +0 -1
- package/utilities/common/omitDeep.d.ts.map +0 -1
- package/utilities/common/stringifyForDisplay.d.ts.map +0 -1
- package/utilities/common/stripTypename.d.ts.map +0 -1
- package/utilities/globals/global.d.ts.map +0 -1
- package/utilities/globals/index.d.ts.map +0 -1
- package/utilities/globals/invariantWrappers.d.ts.map +0 -1
- package/utilities/globals/maybe.d.ts.map +0 -1
- package/utilities/graphql/DocumentTransform.d.ts.map +0 -1
- package/utilities/graphql/directives.d.ts.map +0 -1
- package/utilities/graphql/fragments.d.ts.map +0 -1
- package/utilities/graphql/getFromAST.d.ts.map +0 -1
- package/utilities/graphql/operations.d.ts.map +0 -1
- package/utilities/graphql/print.d.ts.map +0 -1
- package/utilities/graphql/storeUtils.d.ts.map +0 -1
- package/utilities/graphql/transform.d.ts.map +0 -1
- package/utilities/index.d.ts.map +0 -1
- package/utilities/observables/Concast.d.ts.map +0 -1
- package/utilities/observables/Observable.d.ts.map +0 -1
- package/utilities/observables/asyncMap.d.ts.map +0 -1
- package/utilities/observables/iteration.d.ts.map +0 -1
- package/utilities/observables/subclassing.d.ts.map +0 -1
- package/utilities/policies/pagination.d.ts.map +0 -1
- package/utilities/promises/decoration.d.ts.map +0 -1
- package/utilities/types/DeepOmit.d.ts.map +0 -1
- package/utilities/types/DeepPartial.d.ts.map +0 -1
- package/utilities/types/IsStrictlyAny.d.ts.map +0 -1
- package/utilities/types/Primitive.d.ts.map +0 -1
- package/version.d.ts.map +0 -1
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { invariant } from "../../utilities/globals/index.js";
|
|
2
2
|
import { argumentsObjectFromField, DeepMerger, isNonEmptyArray, isNonNullObject, } from "../../utilities/index.js";
|
|
3
3
|
import { hasOwn, isArray } from "./helpers.js";
|
|
4
|
+
// Mapping from JSON-encoded KeySpecifier strings to associated information.
|
|
4
5
|
var specifierInfoCache = Object.create(null);
|
|
5
6
|
function lookupSpecifierInfo(spec) {
|
|
7
|
+
// It's safe to encode KeySpecifier arrays with JSON.stringify, since they're
|
|
8
|
+
// just arrays of strings or nested KeySpecifier arrays, and the order of the
|
|
9
|
+
// array elements is important (and suitably preserved by JSON.stringify).
|
|
6
10
|
var cacheKey = JSON.stringify(spec);
|
|
7
11
|
return (specifierInfoCache[cacheKey] ||
|
|
8
12
|
(specifierInfoCache[cacheKey] = Object.create(null)));
|
|
@@ -14,10 +18,23 @@ export function keyFieldsFnFromSpecifier(specifier) {
|
|
|
14
18
|
return context.readField(key, from);
|
|
15
19
|
};
|
|
16
20
|
var keyObject = (context.keyObject = collectSpecifierPaths(specifier, function (schemaKeyPath) {
|
|
17
|
-
var extracted = extractKeyPath(context.storeObject, schemaKeyPath,
|
|
21
|
+
var extracted = extractKeyPath(context.storeObject, schemaKeyPath,
|
|
22
|
+
// Using context.readField to extract paths from context.storeObject
|
|
23
|
+
// allows the extraction to see through Reference objects and respect
|
|
24
|
+
// custom read functions.
|
|
25
|
+
extract);
|
|
18
26
|
if (extracted === void 0 &&
|
|
19
27
|
object !== context.storeObject &&
|
|
20
28
|
hasOwn.call(object, schemaKeyPath[0])) {
|
|
29
|
+
// If context.storeObject fails to provide a value for the requested
|
|
30
|
+
// path, fall back to the raw result object, if it has a top-level key
|
|
31
|
+
// matching the first key in the path (schemaKeyPath[0]). This allows
|
|
32
|
+
// key fields included in the written data to be saved in the cache
|
|
33
|
+
// even if they are not selected explicitly in context.selectionSet.
|
|
34
|
+
// Not being mentioned by context.selectionSet is convenient here,
|
|
35
|
+
// since it means these extra fields cannot be affected by field
|
|
36
|
+
// aliasing, which is why we can use extractKey instead of
|
|
37
|
+
// context.readField for this extraction.
|
|
21
38
|
extracted = extractKeyPath(object, schemaKeyPath, extractKey);
|
|
22
39
|
}
|
|
23
40
|
invariant(extracted !== void 0, 4, schemaKeyPath.join("."), object);
|
|
@@ -26,6 +43,13 @@ export function keyFieldsFnFromSpecifier(specifier) {
|
|
|
26
43
|
return "".concat(context.typename, ":").concat(JSON.stringify(keyObject));
|
|
27
44
|
}));
|
|
28
45
|
}
|
|
46
|
+
// The keyArgs extraction process is roughly analogous to keyFields extraction,
|
|
47
|
+
// but there are no aliases involved, missing fields are tolerated (by merely
|
|
48
|
+
// omitting them from the key), and drawing from field.directives or variables
|
|
49
|
+
// is allowed (in addition to drawing from the field's arguments object).
|
|
50
|
+
// Concretely, these differences mean passing a different key path extractor
|
|
51
|
+
// function to collectSpecifierPaths, reusing the shared extractKeyPath helper
|
|
52
|
+
// wherever possible.
|
|
29
53
|
export function keyArgsFnFromSpecifier(specifier) {
|
|
30
54
|
var info = lookupSpecifierInfo(specifier);
|
|
31
55
|
return (info.keyArgsFn ||
|
|
@@ -37,11 +61,29 @@ export function keyArgsFnFromSpecifier(specifier) {
|
|
|
37
61
|
if (firstChar === "@") {
|
|
38
62
|
if (field && isNonEmptyArray(field.directives)) {
|
|
39
63
|
var directiveName_1 = firstKey.slice(1);
|
|
64
|
+
// If the directive appears multiple times, only the first
|
|
65
|
+
// occurrence's arguments will be used. TODO Allow repetition?
|
|
66
|
+
// TODO Cache this work somehow, a la aliasMap?
|
|
40
67
|
var d = field.directives.find(function (d) { return d.name.value === directiveName_1; });
|
|
68
|
+
// Fortunately argumentsObjectFromField works for DirectiveNode!
|
|
41
69
|
var directiveArgs = d && argumentsObjectFromField(d, variables);
|
|
70
|
+
// For directives without arguments (d defined, but directiveArgs ===
|
|
71
|
+
// null), the presence or absence of the directive still counts as
|
|
72
|
+
// part of the field key, so we return null in those cases. If no
|
|
73
|
+
// directive with this name was found for this field (d undefined and
|
|
74
|
+
// thus directiveArgs undefined), we return undefined, which causes
|
|
75
|
+
// this value to be omitted from the key object returned by
|
|
76
|
+
// collectSpecifierPaths.
|
|
42
77
|
return (directiveArgs &&
|
|
43
|
-
extractKeyPath(directiveArgs,
|
|
78
|
+
extractKeyPath(directiveArgs,
|
|
79
|
+
// If keyPath.length === 1, this code calls extractKeyPath with an
|
|
80
|
+
// empty path, which works because it uses directiveArgs as the
|
|
81
|
+
// extracted value.
|
|
82
|
+
keyPath.slice(1)));
|
|
44
83
|
}
|
|
84
|
+
// If the key started with @ but there was no corresponding directive,
|
|
85
|
+
// we want to omit this value from the key object, not fall through to
|
|
86
|
+
// treating @whatever as a normal argument name.
|
|
45
87
|
return;
|
|
46
88
|
}
|
|
47
89
|
if (firstChar === "$") {
|
|
@@ -51,6 +93,9 @@ export function keyArgsFnFromSpecifier(specifier) {
|
|
|
51
93
|
varKeyPath[0] = variableName;
|
|
52
94
|
return extractKeyPath(variables, varKeyPath);
|
|
53
95
|
}
|
|
96
|
+
// If the key started with $ but there was no corresponding variable, we
|
|
97
|
+
// want to omit this value from the key object, not fall through to
|
|
98
|
+
// treating $whatever as a normal argument name.
|
|
54
99
|
return;
|
|
55
100
|
}
|
|
56
101
|
if (args) {
|
|
@@ -58,6 +103,11 @@ export function keyArgsFnFromSpecifier(specifier) {
|
|
|
58
103
|
}
|
|
59
104
|
});
|
|
60
105
|
var suffix = JSON.stringify(collected);
|
|
106
|
+
// If no arguments were passed to this field, and it didn't have any other
|
|
107
|
+
// field key contributions from directives or variables, hide the empty
|
|
108
|
+
// :{} suffix from the field key. However, a field passed no arguments can
|
|
109
|
+
// still end up with a non-empty :{...} suffix if its key configuration
|
|
110
|
+
// refers to directives or variables.
|
|
61
111
|
if (args || suffix !== "{}") {
|
|
62
112
|
fieldName += ":" + suffix;
|
|
63
113
|
}
|
|
@@ -65,11 +115,15 @@ export function keyArgsFnFromSpecifier(specifier) {
|
|
|
65
115
|
}));
|
|
66
116
|
}
|
|
67
117
|
export function collectSpecifierPaths(specifier, extractor) {
|
|
118
|
+
// For each path specified by specifier, invoke the extractor, and repeatedly
|
|
119
|
+
// merge the results together, with appropriate ancestor context.
|
|
68
120
|
var merger = new DeepMerger();
|
|
69
121
|
return getSpecifierPaths(specifier).reduce(function (collected, path) {
|
|
70
122
|
var _a;
|
|
71
123
|
var toMerge = extractor(path);
|
|
72
124
|
if (toMerge !== void 0) {
|
|
125
|
+
// This path is not expected to contain array indexes, so the toMerge
|
|
126
|
+
// reconstruction will not contain arrays. TODO Fix this?
|
|
73
127
|
for (var i = path.length - 1; i >= 0; --i) {
|
|
74
128
|
toMerge = (_a = {}, _a[path[i]] = toMerge, _a);
|
|
75
129
|
}
|
|
@@ -103,14 +157,28 @@ function extractKey(object, key) {
|
|
|
103
157
|
return object[key];
|
|
104
158
|
}
|
|
105
159
|
export function extractKeyPath(object, path, extract) {
|
|
160
|
+
// For each key in path, extract the corresponding child property from obj,
|
|
161
|
+
// flattening arrays if encountered (uncommon for keyFields and keyArgs, but
|
|
162
|
+
// possible). The final result of path.reduce is normalized so unexpected leaf
|
|
163
|
+
// objects have their keys safely sorted. That final result is difficult to
|
|
164
|
+
// type as anything other than any. You're welcome to try to improve the
|
|
165
|
+
// return type, but keep in mind extractKeyPath is not a public function
|
|
166
|
+
// (exported only for testing), so the effort may not be worthwhile unless the
|
|
167
|
+
// limited set of actual callers (see above) pass arguments that TypeScript
|
|
168
|
+
// can statically type. If we know only that path is some array of strings
|
|
169
|
+
// (and not, say, a specific tuple of statically known strings), any (or
|
|
170
|
+
// possibly unknown) is the honest answer.
|
|
106
171
|
extract = extract || extractKey;
|
|
107
172
|
return normalize(path.reduce(function reducer(obj, key) {
|
|
108
|
-
return isArray(obj)
|
|
109
|
-
|
|
173
|
+
return isArray(obj) ?
|
|
174
|
+
obj.map(function (child) { return reducer(child, key); })
|
|
110
175
|
: obj && extract(obj, key);
|
|
111
176
|
}, object));
|
|
112
177
|
}
|
|
113
178
|
function normalize(value) {
|
|
179
|
+
// Usually the extracted value will be a scalar value, since most primary
|
|
180
|
+
// key fields are scalar, but just in case we get an object or an array, we
|
|
181
|
+
// need to do some normalization of the order of (nested) keys.
|
|
114
182
|
if (isNonNullObject(value)) {
|
|
115
183
|
if (isArray(value)) {
|
|
116
184
|
return value.map(normalize);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key-extractor.js","sourceRoot":"","sources":["../../../src/cache/inmemory/key-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["import { invariant } from \"../../utilities/globals/index.js\";\n\nimport {\n argumentsObjectFromField,\n DeepMerger,\n isNonEmptyArray,\n isNonNullObject,\n} from \"../../utilities/index.js\";\n\nimport { hasOwn, isArray } from \"./helpers.js\";\nimport type {\n KeySpecifier,\n KeyFieldsFunction,\n KeyArgsFunction,\n} from \"./policies.js\";\n\n// Mapping from JSON-encoded KeySpecifier strings to associated information.\nconst specifierInfoCache: Record<\n string,\n {\n paths?: string[][];\n keyFieldsFn?: KeyFieldsFunction;\n keyArgsFn?: KeyArgsFunction;\n }\n> = Object.create(null);\n\nfunction lookupSpecifierInfo(spec: KeySpecifier) {\n // It's safe to encode KeySpecifier arrays with JSON.stringify, since they're\n // just arrays of strings or nested KeySpecifier arrays, and the order of the\n // array elements is important (and suitably preserved by JSON.stringify).\n const cacheKey = JSON.stringify(spec);\n return (\n specifierInfoCache[cacheKey] ||\n (specifierInfoCache[cacheKey] = Object.create(null))\n );\n}\n\nexport function keyFieldsFnFromSpecifier(\n specifier: KeySpecifier\n): KeyFieldsFunction {\n const info = lookupSpecifierInfo(specifier);\n\n return (\n info.keyFieldsFn ||\n (info.keyFieldsFn = (object, context) => {\n const extract: typeof extractKey = (from, key) =>\n context.readField(key, from);\n\n const keyObject = (context.keyObject = collectSpecifierPaths(\n specifier,\n (schemaKeyPath) => {\n let extracted = extractKeyPath(\n context.storeObject,\n schemaKeyPath,\n // Using context.readField to extract paths from context.storeObject\n // allows the extraction to see through Reference objects and respect\n // custom read functions.\n extract\n );\n\n if (\n extracted === void 0 &&\n object !== context.storeObject &&\n hasOwn.call(object, schemaKeyPath[0])\n ) {\n // If context.storeObject fails to provide a value for the requested\n // path, fall back to the raw result object, if it has a top-level key\n // matching the first key in the path (schemaKeyPath[0]). This allows\n // key fields included in the written data to be saved in the cache\n // even if they are not selected explicitly in context.selectionSet.\n // Not being mentioned by context.selectionSet is convenient here,\n // since it means these extra fields cannot be affected by field\n // aliasing, which is why we can use extractKey instead of\n // context.readField for this extraction.\n extracted = extractKeyPath(object, schemaKeyPath, extractKey);\n }\n\n invariant(\n extracted !== void 0,\n `Missing field '%s' while extracting keyFields from %s`,\n schemaKeyPath.join(\".\"),\n object\n );\n\n return extracted;\n }\n ));\n\n return `${context.typename}:${JSON.stringify(keyObject)}`;\n })\n );\n}\n\n// The keyArgs extraction process is roughly analogous to keyFields extraction,\n// but there are no aliases involved, missing fields are tolerated (by merely\n// omitting them from the key), and drawing from field.directives or variables\n// is allowed (in addition to drawing from the field's arguments object).\n// Concretely, these differences mean passing a different key path extractor\n// function to collectSpecifierPaths, reusing the shared extractKeyPath helper\n// wherever possible.\nexport function keyArgsFnFromSpecifier(\n specifier: KeySpecifier\n): KeyArgsFunction {\n const info = lookupSpecifierInfo(specifier);\n\n return (\n info.keyArgsFn ||\n (info.keyArgsFn = (args, { field, variables, fieldName }) => {\n const collected = collectSpecifierPaths(specifier, (keyPath) => {\n const firstKey = keyPath[0];\n const firstChar = firstKey.charAt(0);\n\n if (firstChar === \"@\") {\n if (field && isNonEmptyArray(field.directives)) {\n const directiveName = firstKey.slice(1);\n // If the directive appears multiple times, only the first\n // occurrence's arguments will be used. TODO Allow repetition?\n // TODO Cache this work somehow, a la aliasMap?\n const d = field.directives.find(\n (d) => d.name.value === directiveName\n );\n // Fortunately argumentsObjectFromField works for DirectiveNode!\n const directiveArgs = d && argumentsObjectFromField(d, variables);\n // For directives without arguments (d defined, but directiveArgs ===\n // null), the presence or absence of the directive still counts as\n // part of the field key, so we return null in those cases. If no\n // directive with this name was found for this field (d undefined and\n // thus directiveArgs undefined), we return undefined, which causes\n // this value to be omitted from the key object returned by\n // collectSpecifierPaths.\n return (\n directiveArgs &&\n extractKeyPath(\n directiveArgs,\n // If keyPath.length === 1, this code calls extractKeyPath with an\n // empty path, which works because it uses directiveArgs as the\n // extracted value.\n keyPath.slice(1)\n )\n );\n }\n // If the key started with @ but there was no corresponding directive,\n // we want to omit this value from the key object, not fall through to\n // treating @whatever as a normal argument name.\n return;\n }\n\n if (firstChar === \"$\") {\n const variableName = firstKey.slice(1);\n if (variables && hasOwn.call(variables, variableName)) {\n const varKeyPath = keyPath.slice(0);\n varKeyPath[0] = variableName;\n return extractKeyPath(variables, varKeyPath);\n }\n // If the key started with $ but there was no corresponding variable, we\n // want to omit this value from the key object, not fall through to\n // treating $whatever as a normal argument name.\n return;\n }\n\n if (args) {\n return extractKeyPath(args, keyPath);\n }\n });\n\n const suffix = JSON.stringify(collected);\n\n // If no arguments were passed to this field, and it didn't have any other\n // field key contributions from directives or variables, hide the empty\n // :{} suffix from the field key. However, a field passed no arguments can\n // still end up with a non-empty :{...} suffix if its key configuration\n // refers to directives or variables.\n if (args || suffix !== \"{}\") {\n fieldName += \":\" + suffix;\n }\n\n return fieldName;\n })\n );\n}\n\nexport function collectSpecifierPaths(\n specifier: KeySpecifier,\n extractor: (path: string[]) => any\n): Record<string, any> {\n // For each path specified by specifier, invoke the extractor, and repeatedly\n // merge the results together, with appropriate ancestor context.\n const merger = new DeepMerger();\n return getSpecifierPaths(specifier).reduce((collected, path) => {\n let toMerge = extractor(path);\n if (toMerge !== void 0) {\n // This path is not expected to contain array indexes, so the toMerge\n // reconstruction will not contain arrays. TODO Fix this?\n for (let i = path.length - 1; i >= 0; --i) {\n toMerge = { [path[i]]: toMerge };\n }\n collected = merger.merge(collected, toMerge);\n }\n return collected;\n }, Object.create(null));\n}\n\nexport function getSpecifierPaths(spec: KeySpecifier): string[][] {\n const info = lookupSpecifierInfo(spec);\n\n if (!info.paths) {\n const paths: string[][] = (info.paths = []);\n const currentPath: string[] = [];\n\n spec.forEach((s, i) => {\n if (isArray(s)) {\n getSpecifierPaths(s).forEach((p) => paths.push(currentPath.concat(p)));\n currentPath.length = 0;\n } else {\n currentPath.push(s);\n if (!isArray(spec[i + 1])) {\n paths.push(currentPath.slice(0));\n currentPath.length = 0;\n }\n }\n });\n }\n\n return info.paths!;\n}\n\nfunction extractKey<TObj extends Record<string, any>, TKey extends string>(\n object: TObj,\n key: TKey\n): TObj[TKey] | undefined {\n return object[key];\n}\n\nexport function extractKeyPath(\n object: Record<string, any>,\n path: string[],\n extract?: typeof extractKey\n): any {\n // For each key in path, extract the corresponding child property from obj,\n // flattening arrays if encountered (uncommon for keyFields and keyArgs, but\n // possible). The final result of path.reduce is normalized so unexpected leaf\n // objects have their keys safely sorted. That final result is difficult to\n // type as anything other than any. You're welcome to try to improve the\n // return type, but keep in mind extractKeyPath is not a public function\n // (exported only for testing), so the effort may not be worthwhile unless the\n // limited set of actual callers (see above) pass arguments that TypeScript\n // can statically type. If we know only that path is some array of strings\n // (and not, say, a specific tuple of statically known strings), any (or\n // possibly unknown) is the honest answer.\n extract = extract || extractKey;\n return normalize(\n path.reduce(function reducer(obj, key): any {\n return isArray(obj)\n ? obj.map((child) => reducer(child, key))\n : obj && extract!(obj, key);\n }, object)\n );\n}\n\nfunction normalize<T>(value: T): T {\n // Usually the extracted value will be a scalar value, since most primary\n // key fields are scalar, but just in case we get an object or an array, we\n // need to do some normalization of the order of (nested) keys.\n if (isNonNullObject(value)) {\n if (isArray(value)) {\n return value.map(normalize) as any;\n }\n return collectSpecifierPaths(Object.keys(value).sort(), (path) =>\n extractKeyPath(value, path)\n ) as T;\n }\n return value;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"key-extractor.js","sourceRoot":"","sources":["../../../src/cache/inmemory/key-extractor.ts"],"names":[],"mappings":"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","sourcesContent":["import { invariant } from \"../../utilities/globals/index.js\";\n\nimport {\n argumentsObjectFromField,\n DeepMerger,\n isNonEmptyArray,\n isNonNullObject,\n} from \"../../utilities/index.js\";\n\nimport { hasOwn, isArray } from \"./helpers.js\";\nimport type {\n KeySpecifier,\n KeyFieldsFunction,\n KeyArgsFunction,\n} from \"./policies.js\";\n\n// Mapping from JSON-encoded KeySpecifier strings to associated information.\nconst specifierInfoCache: Record<\n string,\n {\n paths?: string[][];\n keyFieldsFn?: KeyFieldsFunction;\n keyArgsFn?: KeyArgsFunction;\n }\n> = Object.create(null);\n\nfunction lookupSpecifierInfo(spec: KeySpecifier) {\n // It's safe to encode KeySpecifier arrays with JSON.stringify, since they're\n // just arrays of strings or nested KeySpecifier arrays, and the order of the\n // array elements is important (and suitably preserved by JSON.stringify).\n const cacheKey = JSON.stringify(spec);\n return (\n specifierInfoCache[cacheKey] ||\n (specifierInfoCache[cacheKey] = Object.create(null))\n );\n}\n\nexport function keyFieldsFnFromSpecifier(\n specifier: KeySpecifier\n): KeyFieldsFunction {\n const info = lookupSpecifierInfo(specifier);\n\n return (\n info.keyFieldsFn ||\n (info.keyFieldsFn = (object, context) => {\n const extract: typeof extractKey = (from, key) =>\n context.readField(key, from);\n\n const keyObject = (context.keyObject = collectSpecifierPaths(\n specifier,\n (schemaKeyPath) => {\n let extracted = extractKeyPath(\n context.storeObject,\n schemaKeyPath,\n // Using context.readField to extract paths from context.storeObject\n // allows the extraction to see through Reference objects and respect\n // custom read functions.\n extract\n );\n\n if (\n extracted === void 0 &&\n object !== context.storeObject &&\n hasOwn.call(object, schemaKeyPath[0])\n ) {\n // If context.storeObject fails to provide a value for the requested\n // path, fall back to the raw result object, if it has a top-level key\n // matching the first key in the path (schemaKeyPath[0]). This allows\n // key fields included in the written data to be saved in the cache\n // even if they are not selected explicitly in context.selectionSet.\n // Not being mentioned by context.selectionSet is convenient here,\n // since it means these extra fields cannot be affected by field\n // aliasing, which is why we can use extractKey instead of\n // context.readField for this extraction.\n extracted = extractKeyPath(object, schemaKeyPath, extractKey);\n }\n\n invariant(\n extracted !== void 0,\n `Missing field '%s' while extracting keyFields from %s`,\n schemaKeyPath.join(\".\"),\n object\n );\n\n return extracted;\n }\n ));\n\n return `${context.typename}:${JSON.stringify(keyObject)}`;\n })\n );\n}\n\n// The keyArgs extraction process is roughly analogous to keyFields extraction,\n// but there are no aliases involved, missing fields are tolerated (by merely\n// omitting them from the key), and drawing from field.directives or variables\n// is allowed (in addition to drawing from the field's arguments object).\n// Concretely, these differences mean passing a different key path extractor\n// function to collectSpecifierPaths, reusing the shared extractKeyPath helper\n// wherever possible.\nexport function keyArgsFnFromSpecifier(\n specifier: KeySpecifier\n): KeyArgsFunction {\n const info = lookupSpecifierInfo(specifier);\n\n return (\n info.keyArgsFn ||\n (info.keyArgsFn = (args, { field, variables, fieldName }) => {\n const collected = collectSpecifierPaths(specifier, (keyPath) => {\n const firstKey = keyPath[0];\n const firstChar = firstKey.charAt(0);\n\n if (firstChar === \"@\") {\n if (field && isNonEmptyArray(field.directives)) {\n const directiveName = firstKey.slice(1);\n // If the directive appears multiple times, only the first\n // occurrence's arguments will be used. TODO Allow repetition?\n // TODO Cache this work somehow, a la aliasMap?\n const d = field.directives.find(\n (d) => d.name.value === directiveName\n );\n // Fortunately argumentsObjectFromField works for DirectiveNode!\n const directiveArgs = d && argumentsObjectFromField(d, variables);\n // For directives without arguments (d defined, but directiveArgs ===\n // null), the presence or absence of the directive still counts as\n // part of the field key, so we return null in those cases. If no\n // directive with this name was found for this field (d undefined and\n // thus directiveArgs undefined), we return undefined, which causes\n // this value to be omitted from the key object returned by\n // collectSpecifierPaths.\n return (\n directiveArgs &&\n extractKeyPath(\n directiveArgs,\n // If keyPath.length === 1, this code calls extractKeyPath with an\n // empty path, which works because it uses directiveArgs as the\n // extracted value.\n keyPath.slice(1)\n )\n );\n }\n // If the key started with @ but there was no corresponding directive,\n // we want to omit this value from the key object, not fall through to\n // treating @whatever as a normal argument name.\n return;\n }\n\n if (firstChar === \"$\") {\n const variableName = firstKey.slice(1);\n if (variables && hasOwn.call(variables, variableName)) {\n const varKeyPath = keyPath.slice(0);\n varKeyPath[0] = variableName;\n return extractKeyPath(variables, varKeyPath);\n }\n // If the key started with $ but there was no corresponding variable, we\n // want to omit this value from the key object, not fall through to\n // treating $whatever as a normal argument name.\n return;\n }\n\n if (args) {\n return extractKeyPath(args, keyPath);\n }\n });\n\n const suffix = JSON.stringify(collected);\n\n // If no arguments were passed to this field, and it didn't have any other\n // field key contributions from directives or variables, hide the empty\n // :{} suffix from the field key. However, a field passed no arguments can\n // still end up with a non-empty :{...} suffix if its key configuration\n // refers to directives or variables.\n if (args || suffix !== \"{}\") {\n fieldName += \":\" + suffix;\n }\n\n return fieldName;\n })\n );\n}\n\nexport function collectSpecifierPaths(\n specifier: KeySpecifier,\n extractor: (path: string[]) => any\n): Record<string, any> {\n // For each path specified by specifier, invoke the extractor, and repeatedly\n // merge the results together, with appropriate ancestor context.\n const merger = new DeepMerger();\n return getSpecifierPaths(specifier).reduce((collected, path) => {\n let toMerge = extractor(path);\n if (toMerge !== void 0) {\n // This path is not expected to contain array indexes, so the toMerge\n // reconstruction will not contain arrays. TODO Fix this?\n for (let i = path.length - 1; i >= 0; --i) {\n toMerge = { [path[i]]: toMerge };\n }\n collected = merger.merge(collected, toMerge);\n }\n return collected;\n }, Object.create(null));\n}\n\nexport function getSpecifierPaths(spec: KeySpecifier): string[][] {\n const info = lookupSpecifierInfo(spec);\n\n if (!info.paths) {\n const paths: string[][] = (info.paths = []);\n const currentPath: string[] = [];\n\n spec.forEach((s, i) => {\n if (isArray(s)) {\n getSpecifierPaths(s).forEach((p) => paths.push(currentPath.concat(p)));\n currentPath.length = 0;\n } else {\n currentPath.push(s);\n if (!isArray(spec[i + 1])) {\n paths.push(currentPath.slice(0));\n currentPath.length = 0;\n }\n }\n });\n }\n\n return info.paths!;\n}\n\nfunction extractKey<TObj extends Record<string, any>, TKey extends string>(\n object: TObj,\n key: TKey\n): TObj[TKey] | undefined {\n return object[key];\n}\n\nexport function extractKeyPath(\n object: Record<string, any>,\n path: string[],\n extract?: typeof extractKey\n): any {\n // For each key in path, extract the corresponding child property from obj,\n // flattening arrays if encountered (uncommon for keyFields and keyArgs, but\n // possible). The final result of path.reduce is normalized so unexpected leaf\n // objects have their keys safely sorted. That final result is difficult to\n // type as anything other than any. You're welcome to try to improve the\n // return type, but keep in mind extractKeyPath is not a public function\n // (exported only for testing), so the effort may not be worthwhile unless the\n // limited set of actual callers (see above) pass arguments that TypeScript\n // can statically type. If we know only that path is some array of strings\n // (and not, say, a specific tuple of statically known strings), any (or\n // possibly unknown) is the honest answer.\n extract = extract || extractKey;\n return normalize(\n path.reduce(function reducer(obj, key): any {\n return isArray(obj) ?\n obj.map((child) => reducer(child, key))\n : obj && extract!(obj, key);\n }, object)\n );\n}\n\nfunction normalize<T>(value: T): T {\n // Usually the extracted value will be a scalar value, since most primary\n // key fields are scalar, but just in case we get an object or an array, we\n // need to do some normalization of the order of (nested) keys.\n if (isNonNullObject(value)) {\n if (isArray(value)) {\n return value.map(normalize) as any;\n }\n return collectSpecifierPaths(Object.keys(value).sort(), (path) =>\n extractKeyPath(value, path)\n ) as T;\n }\n return value;\n}\n"]}
|
|
@@ -4,18 +4,81 @@ import { canUseWeakMap, canUseWeakSet, isNonNullObject as isObjectOrArray, } fro
|
|
|
4
4
|
import { isArray } from "./helpers.js";
|
|
5
5
|
function shallowCopy(value) {
|
|
6
6
|
if (isObjectOrArray(value)) {
|
|
7
|
-
return isArray(value)
|
|
8
|
-
|
|
7
|
+
return isArray(value) ?
|
|
8
|
+
value.slice(0)
|
|
9
9
|
: __assign({ __proto__: Object.getPrototypeOf(value) }, value);
|
|
10
10
|
}
|
|
11
11
|
return value;
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
// When programmers talk about the "canonical form" of an object, they
|
|
14
|
+
// usually have the following meaning in mind, which I've copied from
|
|
15
|
+
// https://en.wiktionary.org/wiki/canonical_form:
|
|
16
|
+
//
|
|
17
|
+
// 1. A standard or normal presentation of a mathematical entity [or
|
|
18
|
+
// object]. A canonical form is an element of a set of representatives
|
|
19
|
+
// of equivalence classes of forms such that there is a function or
|
|
20
|
+
// procedure which projects every element of each equivalence class
|
|
21
|
+
// onto that one element, the canonical form of that equivalence
|
|
22
|
+
// class. The canonical form is expected to be simpler than the rest of
|
|
23
|
+
// the forms in some way.
|
|
24
|
+
//
|
|
25
|
+
// That's a long-winded way of saying any two objects that have the same
|
|
26
|
+
// canonical form may be considered equivalent, even if they are !==,
|
|
27
|
+
// which usually means the objects are structurally equivalent (deeply
|
|
28
|
+
// equal), but don't necessarily use the same memory.
|
|
29
|
+
//
|
|
30
|
+
// Like a literary or musical canon, this ObjectCanon class represents a
|
|
31
|
+
// collection of unique canonical items (JavaScript objects), with the
|
|
32
|
+
// important property that canon.admit(a) === canon.admit(b) if a and b
|
|
33
|
+
// are deeply equal to each other. In terms of the definition above, the
|
|
34
|
+
// canon.admit method is the "function or procedure which projects every"
|
|
35
|
+
// object "onto that one element, the canonical form."
|
|
36
|
+
//
|
|
37
|
+
// In the worst case, the canonicalization process may involve looking at
|
|
38
|
+
// every property in the provided object tree, so it takes the same order
|
|
39
|
+
// of time as deep equality checking. Fortunately, already-canonicalized
|
|
40
|
+
// objects are returned immediately from canon.admit, so the presence of
|
|
41
|
+
// canonical subtrees tends to speed up canonicalization.
|
|
42
|
+
//
|
|
43
|
+
// Since consumers of canonical objects can check for deep equality in
|
|
44
|
+
// constant time, canonicalizing cache results can massively improve the
|
|
45
|
+
// performance of application code that skips re-rendering unchanged
|
|
46
|
+
// results, such as "pure" UI components in a framework like React.
|
|
47
|
+
//
|
|
48
|
+
// Of course, since canonical objects may be shared widely between
|
|
49
|
+
// unrelated consumers, it's important to think of them as immutable, even
|
|
50
|
+
// though they are not actually frozen with Object.freeze in production,
|
|
51
|
+
// due to the extra performance overhead that comes with frozen objects.
|
|
52
|
+
//
|
|
53
|
+
// Custom scalar objects whose internal class name is neither Array nor
|
|
54
|
+
// Object can be included safely in the admitted tree, but they will not
|
|
55
|
+
// be replaced with a canonical version (to put it another way, they are
|
|
56
|
+
// assumed to be canonical already).
|
|
57
|
+
//
|
|
58
|
+
// If we ignore custom objects, no detection of cycles or repeated object
|
|
59
|
+
// references is currently required by the StoreReader class, since
|
|
60
|
+
// GraphQL result objects are JSON-serializable trees (and thus contain
|
|
61
|
+
// neither cycles nor repeated subtrees), so we can avoid the complexity
|
|
62
|
+
// of keeping track of objects we've already seen during the recursion of
|
|
63
|
+
// the admit method.
|
|
64
|
+
//
|
|
65
|
+
// In the future, we may consider adding additional cases to the switch
|
|
66
|
+
// statement to handle other common object types, such as "[object Date]"
|
|
67
|
+
// objects, as needed.
|
|
68
|
+
var ObjectCanon = /** @class */ (function () {
|
|
14
69
|
function ObjectCanon() {
|
|
70
|
+
// Set of all canonical objects this ObjectCanon has admitted, allowing
|
|
71
|
+
// canon.admit to return previously-canonicalized objects immediately.
|
|
15
72
|
this.known = new (canUseWeakSet ? WeakSet : Set)();
|
|
73
|
+
// Efficient storage/lookup structure for canonical objects.
|
|
16
74
|
this.pool = new Trie(canUseWeakMap);
|
|
75
|
+
// Make the ObjectCanon assume this value has already been
|
|
76
|
+
// canonicalized.
|
|
17
77
|
this.passes = new WeakMap();
|
|
78
|
+
// Arrays that contain the same elements in a different order can share
|
|
79
|
+
// the same SortedKeysInfo object, to save memory.
|
|
18
80
|
this.keysByJSON = new Map();
|
|
81
|
+
// This has to come last because it depends on keysByJSON.
|
|
19
82
|
this.empty = this.admit({});
|
|
20
83
|
}
|
|
21
84
|
ObjectCanon.prototype.isKnown = function (value) {
|
|
@@ -41,9 +104,15 @@ var ObjectCanon = (function () {
|
|
|
41
104
|
if (this.known.has(value))
|
|
42
105
|
return value;
|
|
43
106
|
var array = value.map(this.admit, this);
|
|
107
|
+
// Arrays are looked up in the Trie using their recursively
|
|
108
|
+
// canonicalized elements, and the known version of the array is
|
|
109
|
+
// preserved as node.array.
|
|
44
110
|
var node = this.pool.lookupArray(array);
|
|
45
111
|
if (!node.array) {
|
|
46
112
|
this.known.add((node.array = array));
|
|
113
|
+
// Since canonical arrays may be shared widely between
|
|
114
|
+
// unrelated consumers, it's important to regard them as
|
|
115
|
+
// immutable, even if they are not frozen in production.
|
|
47
116
|
if (globalThis.__DEV__ !== false) {
|
|
48
117
|
Object.freeze(array);
|
|
49
118
|
}
|
|
@@ -62,6 +131,14 @@ var ObjectCanon = (function () {
|
|
|
62
131
|
keys.sorted.forEach(function (key) {
|
|
63
132
|
array_1.push(_this.admit(value[key]));
|
|
64
133
|
});
|
|
134
|
+
// Objects are looked up in the Trie by their prototype (which
|
|
135
|
+
// is *not* recursively canonicalized), followed by a JSON
|
|
136
|
+
// representation of their (sorted) keys, followed by the
|
|
137
|
+
// sequence of recursively canonicalized values corresponding to
|
|
138
|
+
// those keys. To keep the final results unambiguous with other
|
|
139
|
+
// sequences (such as arrays that just happen to contain [proto,
|
|
140
|
+
// keys.json, value1, value2, ...]), the known version of the
|
|
141
|
+
// object is stored as node.object.
|
|
65
142
|
var node = this.pool.lookupArray(array_1);
|
|
66
143
|
if (!node.object) {
|
|
67
144
|
var obj_1 = (node.object = Object.create(proto_1));
|
|
@@ -69,6 +146,9 @@ var ObjectCanon = (function () {
|
|
|
69
146
|
keys.sorted.forEach(function (key, i) {
|
|
70
147
|
obj_1[key] = array_1[firstValueIndex_1 + i];
|
|
71
148
|
});
|
|
149
|
+
// Since canonical objects may be shared widely between
|
|
150
|
+
// unrelated consumers, it's important to regard them as
|
|
151
|
+
// immutable, even if they are not frozen in production.
|
|
72
152
|
if (globalThis.__DEV__ !== false) {
|
|
73
153
|
Object.freeze(obj_1);
|
|
74
154
|
}
|
|
@@ -79,6 +159,10 @@ var ObjectCanon = (function () {
|
|
|
79
159
|
}
|
|
80
160
|
return value;
|
|
81
161
|
};
|
|
162
|
+
// It's worthwhile to cache the sorting of arrays of strings, since the
|
|
163
|
+
// same initial unsorted arrays tend to be encountered many times.
|
|
164
|
+
// Fortunately, we can reuse the Trie machinery to look up the sorted
|
|
165
|
+
// arrays in linear time (which is faster than sorting large arrays).
|
|
82
166
|
ObjectCanon.prototype.sortedKeys = function (obj) {
|
|
83
167
|
var keys = Object.keys(obj);
|
|
84
168
|
var node = this.pool.lookupArray(keys);
|
|
@@ -94,6 +178,9 @@ var ObjectCanon = (function () {
|
|
|
94
178
|
return ObjectCanon;
|
|
95
179
|
}());
|
|
96
180
|
export { ObjectCanon };
|
|
181
|
+
// Since the keys of canonical objects are always created in lexicographically
|
|
182
|
+
// sorted order, we can use the ObjectCanon to implement a fast and stable
|
|
183
|
+
// version of JSON.stringify, which automatically sorts object keys.
|
|
97
184
|
export var canonicalStringify = Object.assign(function (value) {
|
|
98
185
|
if (isObjectOrArray(value)) {
|
|
99
186
|
if (stringifyCanon === void 0) {
|
|
@@ -110,6 +197,7 @@ export var canonicalStringify = Object.assign(function (value) {
|
|
|
110
197
|
}, {
|
|
111
198
|
reset: resetCanonicalStringify,
|
|
112
199
|
});
|
|
200
|
+
// Can be reset by calling canonicalStringify.reset().
|
|
113
201
|
var stringifyCanon;
|
|
114
202
|
var stringifyCache;
|
|
115
203
|
function resetCanonicalStringify() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-canon.js","sourceRoot":"","sources":["../../../src/cache/inmemory/object-canon.ts"],"names":[],"mappings":"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","sourcesContent":["import { Trie } from \"@wry/trie\";\nimport {\n canUseWeakMap,\n canUseWeakSet,\n isNonNullObject as isObjectOrArray,\n} from \"../../utilities/index.js\";\nimport { isArray } from \"./helpers.js\";\n\nfunction shallowCopy<T>(value: T): T {\n if (isObjectOrArray(value)) {\n return isArray(value)\n ? (value.slice(0) as any as T)\n : { __proto__: Object.getPrototypeOf(value), ...value };\n }\n return value;\n}\n\n// When programmers talk about the \"canonical form\" of an object, they\n// usually have the following meaning in mind, which I've copied from\n// https://en.wiktionary.org/wiki/canonical_form:\n//\n// 1. A standard or normal presentation of a mathematical entity [or\n// object]. A canonical form is an element of a set of representatives\n// of equivalence classes of forms such that there is a function or\n// procedure which projects every element of each equivalence class\n// onto that one element, the canonical form of that equivalence\n// class. The canonical form is expected to be simpler than the rest of\n// the forms in some way.\n//\n// That's a long-winded way of saying any two objects that have the same\n// canonical form may be considered equivalent, even if they are !==,\n// which usually means the objects are structurally equivalent (deeply\n// equal), but don't necessarily use the same memory.\n//\n// Like a literary or musical canon, this ObjectCanon class represents a\n// collection of unique canonical items (JavaScript objects), with the\n// important property that canon.admit(a) === canon.admit(b) if a and b\n// are deeply equal to each other. In terms of the definition above, the\n// canon.admit method is the \"function or procedure which projects every\"\n// object \"onto that one element, the canonical form.\"\n//\n// In the worst case, the canonicalization process may involve looking at\n// every property in the provided object tree, so it takes the same order\n// of time as deep equality checking. Fortunately, already-canonicalized\n// objects are returned immediately from canon.admit, so the presence of\n// canonical subtrees tends to speed up canonicalization.\n//\n// Since consumers of canonical objects can check for deep equality in\n// constant time, canonicalizing cache results can massively improve the\n// performance of application code that skips re-rendering unchanged\n// results, such as \"pure\" UI components in a framework like React.\n//\n// Of course, since canonical objects may be shared widely between\n// unrelated consumers, it's important to think of them as immutable, even\n// though they are not actually frozen with Object.freeze in production,\n// due to the extra performance overhead that comes with frozen objects.\n//\n// Custom scalar objects whose internal class name is neither Array nor\n// Object can be included safely in the admitted tree, but they will not\n// be replaced with a canonical version (to put it another way, they are\n// assumed to be canonical already).\n//\n// If we ignore custom objects, no detection of cycles or repeated object\n// references is currently required by the StoreReader class, since\n// GraphQL result objects are JSON-serializable trees (and thus contain\n// neither cycles nor repeated subtrees), so we can avoid the complexity\n// of keeping track of objects we've already seen during the recursion of\n// the admit method.\n//\n// In the future, we may consider adding additional cases to the switch\n// statement to handle other common object types, such as \"[object Date]\"\n// objects, as needed.\nexport class ObjectCanon {\n // Set of all canonical objects this ObjectCanon has admitted, allowing\n // canon.admit to return previously-canonicalized objects immediately.\n private known = new (canUseWeakSet ? WeakSet : Set)<object>();\n\n // Efficient storage/lookup structure for canonical objects.\n private pool = new Trie<{\n array?: any[];\n object?: Record<string, any>;\n keys?: SortedKeysInfo;\n }>(canUseWeakMap);\n\n public isKnown(value: any): boolean {\n return isObjectOrArray(value) && this.known.has(value);\n }\n\n // Make the ObjectCanon assume this value has already been\n // canonicalized.\n private passes = new WeakMap<object, object>();\n public pass<T>(value: T): T;\n public pass(value: any) {\n if (isObjectOrArray(value)) {\n const copy = shallowCopy(value);\n this.passes.set(copy, value);\n return copy;\n }\n return value;\n }\n\n // Returns the canonical version of value.\n public admit<T>(value: T): T;\n public admit(value: any) {\n if (isObjectOrArray(value)) {\n const original = this.passes.get(value);\n if (original) return original;\n\n const proto = Object.getPrototypeOf(value);\n switch (proto) {\n case Array.prototype: {\n if (this.known.has(value)) return value;\n const array: any[] = (value as any[]).map(this.admit, this);\n // Arrays are looked up in the Trie using their recursively\n // canonicalized elements, and the known version of the array is\n // preserved as node.array.\n const node = this.pool.lookupArray(array);\n if (!node.array) {\n this.known.add((node.array = array));\n // Since canonical arrays may be shared widely between\n // unrelated consumers, it's important to regard them as\n // immutable, even if they are not frozen in production.\n if (__DEV__) {\n Object.freeze(array);\n }\n }\n return node.array;\n }\n\n case null:\n case Object.prototype: {\n if (this.known.has(value)) return value;\n const proto = Object.getPrototypeOf(value);\n const array = [proto];\n const keys = this.sortedKeys(value);\n array.push(keys.json);\n const firstValueIndex = array.length;\n keys.sorted.forEach((key) => {\n array.push(this.admit((value as any)[key]));\n });\n // Objects are looked up in the Trie by their prototype (which\n // is *not* recursively canonicalized), followed by a JSON\n // representation of their (sorted) keys, followed by the\n // sequence of recursively canonicalized values corresponding to\n // those keys. To keep the final results unambiguous with other\n // sequences (such as arrays that just happen to contain [proto,\n // keys.json, value1, value2, ...]), the known version of the\n // object is stored as node.object.\n const node = this.pool.lookupArray(array);\n if (!node.object) {\n const obj = (node.object = Object.create(proto));\n this.known.add(obj);\n keys.sorted.forEach((key, i) => {\n obj[key] = array[firstValueIndex + i];\n });\n // Since canonical objects may be shared widely between\n // unrelated consumers, it's important to regard them as\n // immutable, even if they are not frozen in production.\n if (__DEV__) {\n Object.freeze(obj);\n }\n }\n return node.object;\n }\n }\n }\n return value;\n }\n\n // It's worthwhile to cache the sorting of arrays of strings, since the\n // same initial unsorted arrays tend to be encountered many times.\n // Fortunately, we can reuse the Trie machinery to look up the sorted\n // arrays in linear time (which is faster than sorting large arrays).\n private sortedKeys(obj: object) {\n const keys = Object.keys(obj);\n const node = this.pool.lookupArray(keys);\n if (!node.keys) {\n keys.sort();\n const json = JSON.stringify(keys);\n if (!(node.keys = this.keysByJSON.get(json))) {\n this.keysByJSON.set(json, (node.keys = { sorted: keys, json }));\n }\n }\n return node.keys;\n }\n // Arrays that contain the same elements in a different order can share\n // the same SortedKeysInfo object, to save memory.\n private keysByJSON = new Map<string, SortedKeysInfo>();\n\n // This has to come last because it depends on keysByJSON.\n public readonly empty = this.admit({});\n}\n\ntype SortedKeysInfo = {\n sorted: string[];\n json: string;\n};\n\n// Since the keys of canonical objects are always created in lexicographically\n// sorted order, we can use the ObjectCanon to implement a fast and stable\n// version of JSON.stringify, which automatically sorts object keys.\nexport const canonicalStringify = Object.assign(\n function (value: any): string {\n if (isObjectOrArray(value)) {\n if (stringifyCanon === void 0) {\n resetCanonicalStringify();\n }\n const canonical = stringifyCanon.admit(value);\n let json = stringifyCache.get(canonical);\n if (json === void 0) {\n stringifyCache.set(canonical, (json = JSON.stringify(canonical)));\n }\n return json;\n }\n return JSON.stringify(value);\n },\n {\n reset: resetCanonicalStringify,\n }\n);\n\n// Can be reset by calling canonicalStringify.reset().\nlet stringifyCanon: ObjectCanon;\nlet stringifyCache: WeakMap<object, string>;\n\nfunction resetCanonicalStringify() {\n stringifyCanon = new ObjectCanon();\n stringifyCache = new (canUseWeakMap ? WeakMap : Map)();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"object-canon.js","sourceRoot":"","sources":["../../../src/cache/inmemory/object-canon.ts"],"names":[],"mappings":"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","sourcesContent":["import { Trie } from \"@wry/trie\";\nimport {\n canUseWeakMap,\n canUseWeakSet,\n isNonNullObject as isObjectOrArray,\n} from \"../../utilities/index.js\";\nimport { isArray } from \"./helpers.js\";\n\nfunction shallowCopy<T>(value: T): T {\n if (isObjectOrArray(value)) {\n return isArray(value) ?\n (value.slice(0) as any as T)\n : { __proto__: Object.getPrototypeOf(value), ...value };\n }\n return value;\n}\n\n// When programmers talk about the \"canonical form\" of an object, they\n// usually have the following meaning in mind, which I've copied from\n// https://en.wiktionary.org/wiki/canonical_form:\n//\n// 1. A standard or normal presentation of a mathematical entity [or\n// object]. A canonical form is an element of a set of representatives\n// of equivalence classes of forms such that there is a function or\n// procedure which projects every element of each equivalence class\n// onto that one element, the canonical form of that equivalence\n// class. The canonical form is expected to be simpler than the rest of\n// the forms in some way.\n//\n// That's a long-winded way of saying any two objects that have the same\n// canonical form may be considered equivalent, even if they are !==,\n// which usually means the objects are structurally equivalent (deeply\n// equal), but don't necessarily use the same memory.\n//\n// Like a literary or musical canon, this ObjectCanon class represents a\n// collection of unique canonical items (JavaScript objects), with the\n// important property that canon.admit(a) === canon.admit(b) if a and b\n// are deeply equal to each other. In terms of the definition above, the\n// canon.admit method is the \"function or procedure which projects every\"\n// object \"onto that one element, the canonical form.\"\n//\n// In the worst case, the canonicalization process may involve looking at\n// every property in the provided object tree, so it takes the same order\n// of time as deep equality checking. Fortunately, already-canonicalized\n// objects are returned immediately from canon.admit, so the presence of\n// canonical subtrees tends to speed up canonicalization.\n//\n// Since consumers of canonical objects can check for deep equality in\n// constant time, canonicalizing cache results can massively improve the\n// performance of application code that skips re-rendering unchanged\n// results, such as \"pure\" UI components in a framework like React.\n//\n// Of course, since canonical objects may be shared widely between\n// unrelated consumers, it's important to think of them as immutable, even\n// though they are not actually frozen with Object.freeze in production,\n// due to the extra performance overhead that comes with frozen objects.\n//\n// Custom scalar objects whose internal class name is neither Array nor\n// Object can be included safely in the admitted tree, but they will not\n// be replaced with a canonical version (to put it another way, they are\n// assumed to be canonical already).\n//\n// If we ignore custom objects, no detection of cycles or repeated object\n// references is currently required by the StoreReader class, since\n// GraphQL result objects are JSON-serializable trees (and thus contain\n// neither cycles nor repeated subtrees), so we can avoid the complexity\n// of keeping track of objects we've already seen during the recursion of\n// the admit method.\n//\n// In the future, we may consider adding additional cases to the switch\n// statement to handle other common object types, such as \"[object Date]\"\n// objects, as needed.\nexport class ObjectCanon {\n // Set of all canonical objects this ObjectCanon has admitted, allowing\n // canon.admit to return previously-canonicalized objects immediately.\n private known = new (canUseWeakSet ? WeakSet : Set)<object>();\n\n // Efficient storage/lookup structure for canonical objects.\n private pool = new Trie<{\n array?: any[];\n object?: Record<string, any>;\n keys?: SortedKeysInfo;\n }>(canUseWeakMap);\n\n public isKnown(value: any): boolean {\n return isObjectOrArray(value) && this.known.has(value);\n }\n\n // Make the ObjectCanon assume this value has already been\n // canonicalized.\n private passes = new WeakMap<object, object>();\n public pass<T>(value: T): T;\n public pass(value: any) {\n if (isObjectOrArray(value)) {\n const copy = shallowCopy(value);\n this.passes.set(copy, value);\n return copy;\n }\n return value;\n }\n\n // Returns the canonical version of value.\n public admit<T>(value: T): T;\n public admit(value: any) {\n if (isObjectOrArray(value)) {\n const original = this.passes.get(value);\n if (original) return original;\n\n const proto = Object.getPrototypeOf(value);\n switch (proto) {\n case Array.prototype: {\n if (this.known.has(value)) return value;\n const array: any[] = (value as any[]).map(this.admit, this);\n // Arrays are looked up in the Trie using their recursively\n // canonicalized elements, and the known version of the array is\n // preserved as node.array.\n const node = this.pool.lookupArray(array);\n if (!node.array) {\n this.known.add((node.array = array));\n // Since canonical arrays may be shared widely between\n // unrelated consumers, it's important to regard them as\n // immutable, even if they are not frozen in production.\n if (__DEV__) {\n Object.freeze(array);\n }\n }\n return node.array;\n }\n\n case null:\n case Object.prototype: {\n if (this.known.has(value)) return value;\n const proto = Object.getPrototypeOf(value);\n const array = [proto];\n const keys = this.sortedKeys(value);\n array.push(keys.json);\n const firstValueIndex = array.length;\n keys.sorted.forEach((key) => {\n array.push(this.admit((value as any)[key]));\n });\n // Objects are looked up in the Trie by their prototype (which\n // is *not* recursively canonicalized), followed by a JSON\n // representation of their (sorted) keys, followed by the\n // sequence of recursively canonicalized values corresponding to\n // those keys. To keep the final results unambiguous with other\n // sequences (such as arrays that just happen to contain [proto,\n // keys.json, value1, value2, ...]), the known version of the\n // object is stored as node.object.\n const node = this.pool.lookupArray(array);\n if (!node.object) {\n const obj = (node.object = Object.create(proto));\n this.known.add(obj);\n keys.sorted.forEach((key, i) => {\n obj[key] = array[firstValueIndex + i];\n });\n // Since canonical objects may be shared widely between\n // unrelated consumers, it's important to regard them as\n // immutable, even if they are not frozen in production.\n if (__DEV__) {\n Object.freeze(obj);\n }\n }\n return node.object;\n }\n }\n }\n return value;\n }\n\n // It's worthwhile to cache the sorting of arrays of strings, since the\n // same initial unsorted arrays tend to be encountered many times.\n // Fortunately, we can reuse the Trie machinery to look up the sorted\n // arrays in linear time (which is faster than sorting large arrays).\n private sortedKeys(obj: object) {\n const keys = Object.keys(obj);\n const node = this.pool.lookupArray(keys);\n if (!node.keys) {\n keys.sort();\n const json = JSON.stringify(keys);\n if (!(node.keys = this.keysByJSON.get(json))) {\n this.keysByJSON.set(json, (node.keys = { sorted: keys, json }));\n }\n }\n return node.keys;\n }\n // Arrays that contain the same elements in a different order can share\n // the same SortedKeysInfo object, to save memory.\n private keysByJSON = new Map<string, SortedKeysInfo>();\n\n // This has to come last because it depends on keysByJSON.\n public readonly empty = this.admit({});\n}\n\ntype SortedKeysInfo = {\n sorted: string[];\n json: string;\n};\n\n// Since the keys of canonical objects are always created in lexicographically\n// sorted order, we can use the ObjectCanon to implement a fast and stable\n// version of JSON.stringify, which automatically sorts object keys.\nexport const canonicalStringify = Object.assign(\n function (value: any): string {\n if (isObjectOrArray(value)) {\n if (stringifyCanon === void 0) {\n resetCanonicalStringify();\n }\n const canonical = stringifyCanon.admit(value);\n let json = stringifyCache.get(canonical);\n if (json === void 0) {\n stringifyCache.set(canonical, (json = JSON.stringify(canonical)));\n }\n return json;\n }\n return JSON.stringify(value);\n },\n {\n reset: resetCanonicalStringify,\n }\n);\n\n// Can be reset by calling canonicalStringify.reset().\nlet stringifyCanon: ObjectCanon;\nlet stringifyCache: WeakMap<object, string>;\n\nfunction resetCanonicalStringify() {\n stringifyCanon = new ObjectCanon();\n stringifyCache = new (canUseWeakMap ? WeakMap : Map)();\n}\n"]}
|