@apollo/client 4.0.11 → 4.0.12
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 +6 -0
- package/__cjs/cache/core/cache.cjs +48 -5
- package/__cjs/cache/core/cache.cjs.map +1 -1
- package/__cjs/cache/core/cache.d.cts +47 -0
- package/__cjs/cache/core/types/Cache.d.cts +28 -0
- package/__cjs/cache/inmemory/fragmentRegistry.cjs +5 -0
- package/__cjs/cache/inmemory/fragmentRegistry.cjs.map +1 -1
- package/__cjs/cache/inmemory/inMemoryCache.cjs +47 -0
- package/__cjs/cache/inmemory/inMemoryCache.cjs.map +1 -1
- package/__cjs/cache/inmemory/inMemoryCache.d.cts +47 -0
- package/__cjs/link/error/index.cjs +1 -1
- package/__cjs/link/error/index.cjs.map +1 -1
- package/__cjs/link/error/index.d.cts +1 -1
- package/__cjs/link/remove-typename/removeTypenameFromVariables.cjs +51 -50
- package/__cjs/link/remove-typename/removeTypenameFromVariables.cjs.map +1 -1
- package/__cjs/link/remove-typename/removeTypenameFromVariables.d.cts +3 -0
- package/__cjs/react/hooks/useApolloClient.cjs +1 -1
- package/__cjs/react/hooks/useApolloClient.cjs.map +1 -1
- package/__cjs/react/hooks/useApolloClient.d.cts +1 -1
- package/__cjs/utilities/internal/bindCacheKey.cjs +21 -0
- package/__cjs/utilities/internal/bindCacheKey.cjs.map +1 -0
- package/__cjs/utilities/internal/bindCacheKey.d.cts +15 -0
- package/__cjs/utilities/internal/index.cjs +3 -1
- package/__cjs/utilities/internal/index.cjs.map +1 -1
- package/__cjs/utilities/internal/index.d.cts +1 -0
- package/__cjs/version.cjs +1 -1
- package/cache/core/cache.d.ts +47 -0
- package/cache/core/cache.js +49 -6
- package/cache/core/cache.js.map +1 -1
- package/cache/core/types/Cache.d.ts +28 -0
- package/cache/core/types/Cache.js.map +1 -1
- package/cache/inmemory/fragmentRegistry.js +6 -1
- package/cache/inmemory/fragmentRegistry.js.map +1 -1
- package/cache/inmemory/inMemoryCache.d.ts +47 -0
- package/cache/inmemory/inMemoryCache.js +47 -0
- package/cache/inmemory/inMemoryCache.js.map +1 -1
- package/link/error/index.d.ts +1 -1
- package/link/error/index.js +1 -1
- package/link/error/index.js.map +1 -1
- package/link/remove-typename/removeTypenameFromVariables.d.ts +3 -0
- package/link/remove-typename/removeTypenameFromVariables.js +51 -50
- package/link/remove-typename/removeTypenameFromVariables.js.map +1 -1
- package/package.json +1 -1
- package/react/hooks/useApolloClient.d.ts +1 -1
- package/react/hooks/useApolloClient.js +1 -1
- package/react/hooks/useApolloClient.js.map +1 -1
- package/react/hooks-compiled/useApolloClient.d.ts +1 -1
- package/react/hooks-compiled/useApolloClient.js +1 -1
- package/react/hooks-compiled/useApolloClient.js.map +1 -1
- package/utilities/internal/bindCacheKey.d.ts +15 -0
- package/utilities/internal/bindCacheKey.js +18 -0
- package/utilities/internal/bindCacheKey.js.map +1 -0
- package/utilities/internal/index.d.ts +1 -0
- package/utilities/internal/index.js +1 -0
- package/utilities/internal/index.js.map +1 -1
- package/version.js +1 -1
|
@@ -75,9 +75,37 @@ export declare namespace Cache {
|
|
|
75
75
|
broadcast?: boolean;
|
|
76
76
|
}
|
|
77
77
|
interface BatchOptions<TCache extends ApolloCache, TUpdateResult = void> {
|
|
78
|
+
/**
|
|
79
|
+
* A function that performs cache operations. Receives the cache instance as its argument.
|
|
80
|
+
*
|
|
81
|
+
* The return value of this function becomes the return value of `batch`.
|
|
82
|
+
*/
|
|
78
83
|
update(cache: TCache): TUpdateResult;
|
|
84
|
+
/**
|
|
85
|
+
* Controls how optimistic data is handled:
|
|
86
|
+
*
|
|
87
|
+
* - `string`: Creates a new optimistic layer with this ID. Use `removeOptimistic` later to remove it.
|
|
88
|
+
* - `true`: Updates the current top layer of the cache (including any optimistic data).
|
|
89
|
+
* - `false`: Updates only the root (non-optimistic) cache data.
|
|
90
|
+
*
|
|
91
|
+
* @defaultValue false
|
|
92
|
+
*/
|
|
79
93
|
optimistic?: string | boolean;
|
|
94
|
+
/**
|
|
95
|
+
* If provided, removes the optimistic layer with this ID after the batch completes.
|
|
96
|
+
*
|
|
97
|
+
* This is useful for atomically applying server data while removing a pending optimistic update, triggering at most one broadcast for both operations.
|
|
98
|
+
*
|
|
99
|
+
* Note: this option is needed because calling `cache.removeOptimistic` during the transaction function may not be safe, since any modifications to cache layers may be discarded after the transaction finishes.
|
|
100
|
+
*/
|
|
80
101
|
removeOptimistic?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Optional callback invoked for each watcher affected by the batch operation.
|
|
104
|
+
*
|
|
105
|
+
* Receives the watch options, the new diff result, and optionally the previous diff result.
|
|
106
|
+
*
|
|
107
|
+
* Return `false` to prevent broadcasting to that specific watcher.
|
|
108
|
+
*/
|
|
81
109
|
onWatchUpdated?: (this: TCache, watch: Cache.WatchOptions, diff: Cache.DiffResult<any>, lastDiff?: Cache.DiffResult<any> | undefined) => any;
|
|
82
110
|
}
|
|
83
111
|
interface ReadQueryOptions<TData, TVariables extends OperationVariables> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Cache.js","sourceRoot":"","sources":["../../../../src/cache/core/types/Cache.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n DataValue,\n DocumentNode,\n OperationVariables,\n TypedDocumentNode,\n} from \"@apollo/client\";\nimport type { Unmasked } from \"@apollo/client/masking\";\n\nimport type { ApolloCache } from \"../cache.js\";\n\nimport type {\n AllFieldsModifier,\n MissingFieldError,\n Modifiers,\n} from \"./common.js\";\nexport declare namespace Cache {\n export type WatchCallback<TData = unknown> = (\n diff: Cache.DiffResult<TData>,\n lastDiff?: Cache.DiffResult<TData>\n ) => void;\n\n export interface ReadOptions<\n TData = unknown,\n TVariables extends OperationVariables = OperationVariables,\n > {\n /**\n * The GraphQL query shape to be used constructed using the `gql` template\n * string tag from `graphql-tag`. The query will be used to determine the\n * shape of the data to be read.\n */\n query: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * Any variables that the GraphQL query may depend on.\n */\n variables?: TVariables;\n\n /**\n * The root id to be used. Defaults to \"ROOT_QUERY\", which is the ID of the\n * root query object. This property makes writeQuery capable of writing data\n * to any object in the cache.\n */\n id?: string;\n rootId?: string;\n previousResult?: any;\n optimistic: boolean;\n returnPartialData?: boolean;\n }\n\n export interface WriteOptions<\n TData = unknown,\n TVariables extends OperationVariables = OperationVariables,\n > {\n /**\n * The GraphQL query shape to be used constructed using the `gql` template\n * string tag from `graphql-tag`. The query will be used to determine the\n * shape of the data to be read.\n */\n query: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * Any variables that the GraphQL query may depend on.\n */\n variables?: TVariables;\n\n dataId?: string;\n result: Unmasked<TData>;\n\n /**\n * Whether to notify query watchers.\n * @defaultValue true\n */\n broadcast?: boolean;\n /**\n * When true, ignore existing field data rather than merging it with\n * incoming data.\n * @defaultValue false\n */\n overwrite?: boolean;\n }\n\n export interface DiffOptions<\n TData = unknown,\n TVariables extends OperationVariables = OperationVariables,\n > extends Omit<ReadOptions<TData, TVariables>, \"rootId\"> {\n // The DiffOptions interface is currently just an alias for\n // ReadOptions, though DiffOptions used to be responsible for\n // declaring the returnPartialData option.\n }\n\n export interface WatchOptions<\n TData = unknown,\n TVariables extends OperationVariables = OperationVariables,\n > extends DiffOptions<TData, TVariables> {\n watcher?: object;\n immediate?: boolean;\n callback: WatchCallback<TData>;\n lastDiff?: DiffResult<TData>;\n }\n\n export interface EvictOptions {\n id?: string;\n fieldName?: string;\n args?: Record<string, any>;\n broadcast?: boolean;\n }\n\n // Although you can call cache.reset() without options, its behavior can be\n // configured by passing a Cache.ResetOptions object.\n export interface ResetOptions {\n discardWatches?: boolean;\n }\n\n export interface ModifyOptions<\n Entity extends Record<string, any> = Record<string, any>,\n > {\n id?: string;\n fields: Modifiers<Entity> | AllFieldsModifier<Entity>;\n optimistic?: boolean;\n broadcast?: boolean;\n }\n\n export interface BatchOptions<\n TCache extends ApolloCache,\n TUpdateResult = void,\n > {\n // Same as the first parameter of performTransaction, except the cache\n // argument will have the subclass type rather than ApolloCache.\n update(cache: TCache): TUpdateResult;\n\n // Passing a string for this option creates a new optimistic layer, with the\n // given string as its layer.id, just like passing a string for the\n // optimisticId parameter of performTransaction. Passing true is the same as\n // passing undefined to performTransaction (running the batch operation\n // against the current top layer of the cache), and passing false is the\n // same as passing null (running the operation against root/non-optimistic\n // cache data).\n optimistic?: string | boolean;\n\n // If you specify the ID of an optimistic layer using this option, that\n // layer will be removed as part of the batch transaction, triggering at\n // most one broadcast for both the transaction and the removal of the layer.\n // Note: this option is needed because calling cache.removeOptimistic during\n // the transaction function may not be not safe, since any modifications to\n // cache layers may be discarded after the transaction finishes.\n removeOptimistic?: string;\n\n // If you want to find out which watched queries were invalidated during\n // this batch operation, pass this optional callback function. Returning\n // false from the callback will prevent broadcasting this result.\n onWatchUpdated?: (\n this: TCache,\n watch: Cache.WatchOptions,\n diff: Cache.DiffResult<any>,\n lastDiff?: Cache.DiffResult<any> | undefined\n ) => any;\n }\n\n export interface ReadQueryOptions<\n TData,\n TVariables extends OperationVariables,\n > {\n /**\n * The GraphQL query shape to be used constructed using the `gql` template\n * string tag. The query will be used to determine the\n * shape of the data to be read.\n */\n query: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * Any variables that the GraphQL query may depend on.\n */\n variables?: TVariables;\n\n /**\n * The root id to be used. Defaults to \"ROOT_QUERY\", which is the ID of the\n * root query object. This property makes readQuery capable of reading data\n * from any object in the cache.\n */\n id?: string;\n /**\n * Whether to return incomplete data rather than null.\n * @defaultValue false\n */\n returnPartialData?: boolean;\n /**\n * Whether to read from optimistic or non-optimistic cache data. If\n * this named option is provided, the optimistic parameter of the\n * readQuery method can be omitted.\n * @defaultValue false\n */\n optimistic?: boolean;\n }\n\n export interface ReadFragmentOptions<\n TData,\n TVariables extends OperationVariables,\n > {\n /**\n * The root id to be used. This id should take the same form as the\n * value returned by the `cache.identify` function. If a value with your\n * id does not exist in the store, `null` will be returned.\n */\n id?: string;\n\n /**\n * A GraphQL document created using the `gql` template string tag from\n * `graphql-tag` with one or more fragments which will be used to determine\n * the shape of data to read. If you provide more than one fragment in this\n * document then you must also specify `fragmentName` to specify which\n * fragment is the root fragment.\n */\n fragment: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * The name of the fragment in your GraphQL document to be used. If you do\n * not provide a `fragmentName` and there is only one fragment in your\n * `fragment` document then that fragment will be used.\n */\n fragmentName?: string;\n\n /**\n * Any variables that your GraphQL fragments depend on.\n */\n variables?: TVariables;\n\n /**\n * Whether to return incomplete data rather than null.\n * @defaultValue false\n */\n returnPartialData?: boolean;\n /**\n * Whether to read from optimistic or non-optimistic cache data. If\n * this named option is provided, the optimistic parameter of the\n * readFragment method can be omitted.\n * @defaultValue false\n */\n optimistic?: boolean;\n }\n\n export interface WriteQueryOptions<\n TData,\n TVariables extends OperationVariables,\n > {\n /**\n * The GraphQL query shape to be used constructed using the `gql` template\n * string tag from `graphql-tag`. The query will be used to determine the\n * shape of the data to be read.\n */\n query: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * Any variables that the GraphQL query may depend on.\n */\n variables?: TVariables;\n\n /**\n * The root id to be used. Defaults to \"ROOT_QUERY\", which is the ID of the\n * root query object. This property makes writeQuery capable of writing data\n * to any object in the cache.\n */\n id?: string;\n\n /**\n * The data to write to the store.\n */\n data: Unmasked<TData>;\n /**\n * Whether to notify query watchers.\n * @defaultValue true\n */\n broadcast?: boolean;\n /**\n * When true, ignore existing field data rather than merging it with\n * incoming data.\n * @defaultValue false\n */\n overwrite?: boolean;\n }\n\n export interface WriteFragmentOptions<\n TData,\n TVariables extends OperationVariables,\n > {\n /**\n * The root id to be used. This id should take the same form as the\n * value returned by the `cache.identify` function. If a value with your\n * id does not exist in the store, `null` will be returned.\n */\n id?: string;\n\n /**\n * A GraphQL document created using the `gql` template string\n * with one or more fragments which will be used to determine\n * the shape of data to read. If you provide more than one fragment in this\n * document then you must also specify `fragmentName` to specify specify which\n * fragment is the root fragment.\n */\n fragment: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * The name of the fragment in your GraphQL document to be used. If you do\n * not provide a `fragmentName` and there is only one fragment in your\n * `fragment` document then that fragment will be used.\n */\n fragmentName?: string;\n\n /**\n * Any variables that your GraphQL fragments depend on.\n */\n variables?: TVariables;\n /**\n * The data to write to the store.\n */\n data: Unmasked<TData>;\n /**\n * Whether to notify query watchers.\n * @defaultValue true\n */\n broadcast?: boolean;\n /**\n * When true, ignore existing field data rather than merging it with\n * incoming data.\n * @defaultValue false\n */\n overwrite?: boolean;\n }\n\n export interface UpdateQueryOptions<\n TData,\n TVariables extends OperationVariables,\n > extends Omit<\n ReadQueryOptions<TData, TVariables> &\n WriteQueryOptions<TData, TVariables>,\n \"data\"\n > {}\n\n export interface UpdateFragmentOptions<\n TData,\n TVariables extends OperationVariables,\n > extends Omit<\n ReadFragmentOptions<TData, TVariables> &\n WriteFragmentOptions<TData, TVariables>,\n \"data\"\n > {}\n\n export type DiffResult<TData> =\n | {\n result: DataValue.Complete<TData>;\n complete: true;\n missing?: never;\n fromOptimisticTransaction?: boolean;\n }\n | {\n result: DataValue.Partial<TData> | null;\n complete: false;\n missing?: MissingFieldError;\n fromOptimisticTransaction?: boolean;\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Cache.js","sourceRoot":"","sources":["../../../../src/cache/core/types/Cache.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n DataValue,\n DocumentNode,\n OperationVariables,\n TypedDocumentNode,\n} from \"@apollo/client\";\nimport type { Unmasked } from \"@apollo/client/masking\";\n\nimport type { ApolloCache } from \"../cache.js\";\n\nimport type {\n AllFieldsModifier,\n MissingFieldError,\n Modifiers,\n} from \"./common.js\";\nexport declare namespace Cache {\n export type WatchCallback<TData = unknown> = (\n diff: Cache.DiffResult<TData>,\n lastDiff?: Cache.DiffResult<TData>\n ) => void;\n\n export interface ReadOptions<\n TData = unknown,\n TVariables extends OperationVariables = OperationVariables,\n > {\n /**\n * The GraphQL query shape to be used constructed using the `gql` template\n * string tag from `graphql-tag`. The query will be used to determine the\n * shape of the data to be read.\n */\n query: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * Any variables that the GraphQL query may depend on.\n */\n variables?: TVariables;\n\n /**\n * The root id to be used. Defaults to \"ROOT_QUERY\", which is the ID of the\n * root query object. This property makes writeQuery capable of writing data\n * to any object in the cache.\n */\n id?: string;\n rootId?: string;\n previousResult?: any;\n optimistic: boolean;\n returnPartialData?: boolean;\n }\n\n export interface WriteOptions<\n TData = unknown,\n TVariables extends OperationVariables = OperationVariables,\n > {\n /**\n * The GraphQL query shape to be used constructed using the `gql` template\n * string tag from `graphql-tag`. The query will be used to determine the\n * shape of the data to be read.\n */\n query: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * Any variables that the GraphQL query may depend on.\n */\n variables?: TVariables;\n\n dataId?: string;\n result: Unmasked<TData>;\n\n /**\n * Whether to notify query watchers.\n * @defaultValue true\n */\n broadcast?: boolean;\n /**\n * When true, ignore existing field data rather than merging it with\n * incoming data.\n * @defaultValue false\n */\n overwrite?: boolean;\n }\n\n export interface DiffOptions<\n TData = unknown,\n TVariables extends OperationVariables = OperationVariables,\n > extends Omit<ReadOptions<TData, TVariables>, \"rootId\"> {\n // The DiffOptions interface is currently just an alias for\n // ReadOptions, though DiffOptions used to be responsible for\n // declaring the returnPartialData option.\n }\n\n export interface WatchOptions<\n TData = unknown,\n TVariables extends OperationVariables = OperationVariables,\n > extends DiffOptions<TData, TVariables> {\n watcher?: object;\n immediate?: boolean;\n callback: WatchCallback<TData>;\n lastDiff?: DiffResult<TData>;\n }\n\n export interface EvictOptions {\n id?: string;\n fieldName?: string;\n args?: Record<string, any>;\n broadcast?: boolean;\n }\n\n // Although you can call cache.reset() without options, its behavior can be\n // configured by passing a Cache.ResetOptions object.\n export interface ResetOptions {\n discardWatches?: boolean;\n }\n\n export interface ModifyOptions<\n Entity extends Record<string, any> = Record<string, any>,\n > {\n id?: string;\n fields: Modifiers<Entity> | AllFieldsModifier<Entity>;\n optimistic?: boolean;\n broadcast?: boolean;\n }\n\n export interface BatchOptions<\n TCache extends ApolloCache,\n TUpdateResult = void,\n > {\n /**\n * A function that performs cache operations. Receives the cache instance as its argument.\n *\n * The return value of this function becomes the return value of `batch`.\n */\n update(cache: TCache): TUpdateResult;\n\n /**\n * Controls how optimistic data is handled:\n *\n * - `string`: Creates a new optimistic layer with this ID. Use `removeOptimistic` later to remove it.\n * - `true`: Updates the current top layer of the cache (including any optimistic data).\n * - `false`: Updates only the root (non-optimistic) cache data.\n *\n * @defaultValue false\n */\n optimistic?: string | boolean;\n\n /**\n * If provided, removes the optimistic layer with this ID after the batch completes.\n *\n * This is useful for atomically applying server data while removing a pending optimistic update, triggering at most one broadcast for both operations.\n *\n * Note: this option is needed because calling `cache.removeOptimistic` during the transaction function may not be safe, since any modifications to cache layers may be discarded after the transaction finishes.\n */\n removeOptimistic?: string;\n\n /**\n * Optional callback invoked for each watcher affected by the batch operation.\n *\n * Receives the watch options, the new diff result, and optionally the previous diff result.\n *\n * Return `false` to prevent broadcasting to that specific watcher.\n */\n onWatchUpdated?: (\n this: TCache,\n watch: Cache.WatchOptions,\n diff: Cache.DiffResult<any>,\n lastDiff?: Cache.DiffResult<any> | undefined\n ) => any;\n }\n\n export interface ReadQueryOptions<\n TData,\n TVariables extends OperationVariables,\n > {\n /**\n * The GraphQL query shape to be used constructed using the `gql` template\n * string tag. The query will be used to determine the\n * shape of the data to be read.\n */\n query: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * Any variables that the GraphQL query may depend on.\n */\n variables?: TVariables;\n\n /**\n * The root id to be used. Defaults to \"ROOT_QUERY\", which is the ID of the\n * root query object. This property makes readQuery capable of reading data\n * from any object in the cache.\n */\n id?: string;\n /**\n * Whether to return incomplete data rather than null.\n * @defaultValue false\n */\n returnPartialData?: boolean;\n /**\n * Whether to read from optimistic or non-optimistic cache data. If\n * this named option is provided, the optimistic parameter of the\n * readQuery method can be omitted.\n * @defaultValue false\n */\n optimistic?: boolean;\n }\n\n export interface ReadFragmentOptions<\n TData,\n TVariables extends OperationVariables,\n > {\n /**\n * The root id to be used. This id should take the same form as the\n * value returned by the `cache.identify` function. If a value with your\n * id does not exist in the store, `null` will be returned.\n */\n id?: string;\n\n /**\n * A GraphQL document created using the `gql` template string tag from\n * `graphql-tag` with one or more fragments which will be used to determine\n * the shape of data to read. If you provide more than one fragment in this\n * document then you must also specify `fragmentName` to specify which\n * fragment is the root fragment.\n */\n fragment: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * The name of the fragment in your GraphQL document to be used. If you do\n * not provide a `fragmentName` and there is only one fragment in your\n * `fragment` document then that fragment will be used.\n */\n fragmentName?: string;\n\n /**\n * Any variables that your GraphQL fragments depend on.\n */\n variables?: TVariables;\n\n /**\n * Whether to return incomplete data rather than null.\n * @defaultValue false\n */\n returnPartialData?: boolean;\n /**\n * Whether to read from optimistic or non-optimistic cache data. If\n * this named option is provided, the optimistic parameter of the\n * readFragment method can be omitted.\n * @defaultValue false\n */\n optimistic?: boolean;\n }\n\n export interface WriteQueryOptions<\n TData,\n TVariables extends OperationVariables,\n > {\n /**\n * The GraphQL query shape to be used constructed using the `gql` template\n * string tag from `graphql-tag`. The query will be used to determine the\n * shape of the data to be read.\n */\n query: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * Any variables that the GraphQL query may depend on.\n */\n variables?: TVariables;\n\n /**\n * The root id to be used. Defaults to \"ROOT_QUERY\", which is the ID of the\n * root query object. This property makes writeQuery capable of writing data\n * to any object in the cache.\n */\n id?: string;\n\n /**\n * The data to write to the store.\n */\n data: Unmasked<TData>;\n /**\n * Whether to notify query watchers.\n * @defaultValue true\n */\n broadcast?: boolean;\n /**\n * When true, ignore existing field data rather than merging it with\n * incoming data.\n * @defaultValue false\n */\n overwrite?: boolean;\n }\n\n export interface WriteFragmentOptions<\n TData,\n TVariables extends OperationVariables,\n > {\n /**\n * The root id to be used. This id should take the same form as the\n * value returned by the `cache.identify` function. If a value with your\n * id does not exist in the store, `null` will be returned.\n */\n id?: string;\n\n /**\n * A GraphQL document created using the `gql` template string\n * with one or more fragments which will be used to determine\n * the shape of data to read. If you provide more than one fragment in this\n * document then you must also specify `fragmentName` to specify specify which\n * fragment is the root fragment.\n */\n fragment: DocumentNode | TypedDocumentNode<TData, TVariables>;\n\n /**\n * The name of the fragment in your GraphQL document to be used. If you do\n * not provide a `fragmentName` and there is only one fragment in your\n * `fragment` document then that fragment will be used.\n */\n fragmentName?: string;\n\n /**\n * Any variables that your GraphQL fragments depend on.\n */\n variables?: TVariables;\n /**\n * The data to write to the store.\n */\n data: Unmasked<TData>;\n /**\n * Whether to notify query watchers.\n * @defaultValue true\n */\n broadcast?: boolean;\n /**\n * When true, ignore existing field data rather than merging it with\n * incoming data.\n * @defaultValue false\n */\n overwrite?: boolean;\n }\n\n export interface UpdateQueryOptions<\n TData,\n TVariables extends OperationVariables,\n > extends Omit<\n ReadQueryOptions<TData, TVariables> &\n WriteQueryOptions<TData, TVariables>,\n \"data\"\n > {}\n\n export interface UpdateFragmentOptions<\n TData,\n TVariables extends OperationVariables,\n > extends Omit<\n ReadFragmentOptions<TData, TVariables> &\n WriteFragmentOptions<TData, TVariables>,\n \"data\"\n > {}\n\n export type DiffResult<TData> =\n | {\n result: DataValue.Complete<TData>;\n complete: true;\n missing?: never;\n fromOptimisticTransaction?: boolean;\n }\n | {\n result: DataValue.Partial<TData> | null;\n complete: false;\n missing?: MissingFieldError;\n fromOptimisticTransaction?: boolean;\n };\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import { WeakCache } from "@wry/caches";
|
|
|
2
2
|
import { visit } from "graphql";
|
|
3
3
|
import { wrap } from "optimism";
|
|
4
4
|
import { cacheSizes } from "@apollo/client/utilities";
|
|
5
|
-
import { getFragmentDefinitions } from "@apollo/client/utilities/internal";
|
|
5
|
+
import { bindCacheKey, getFragmentDefinitions, } from "@apollo/client/utilities/internal";
|
|
6
6
|
// As long as createFragmentRegistry is not imported or used, the
|
|
7
7
|
// FragmentRegistry example implementation provided below should not be bundled
|
|
8
8
|
// (by tree-shaking bundlers like Rollup), because the implementation of
|
|
@@ -43,16 +43,21 @@ class FragmentRegistry {
|
|
|
43
43
|
resetCaches() {
|
|
44
44
|
const proto = FragmentRegistry.prototype;
|
|
45
45
|
this.invalidate = (this.lookup = wrap(proto.lookup.bind(this), {
|
|
46
|
+
// This is intentionally an identity function - a string cannot be keyed weakly.
|
|
47
|
+
// This is not a memory leak, as lifetime is bound to the `FragmentRegistry` instance,
|
|
48
|
+
// and max size is configurable.
|
|
46
49
|
makeCacheKey: (arg) => arg,
|
|
47
50
|
max: cacheSizes["fragmentRegistry.lookup"] ||
|
|
48
51
|
1000 /* defaultCacheSizes["fragmentRegistry.lookup"] */,
|
|
49
52
|
})).dirty; // This dirty function is bound to the wrapped lookup method.
|
|
50
53
|
this.transform = wrap(proto.transform.bind(this), {
|
|
54
|
+
makeCacheKey: bindCacheKey(this),
|
|
51
55
|
cache: WeakCache,
|
|
52
56
|
max: cacheSizes["fragmentRegistry.transform"] ||
|
|
53
57
|
2000 /* defaultCacheSizes["fragmentRegistry.transform"] */,
|
|
54
58
|
});
|
|
55
59
|
this.findFragmentSpreads = wrap(proto.findFragmentSpreads.bind(this), {
|
|
60
|
+
makeCacheKey: bindCacheKey(this),
|
|
56
61
|
cache: WeakCache,
|
|
57
62
|
max: cacheSizes["fragmentRegistry.findFragmentSpreads"] ||
|
|
58
63
|
4000 /* defaultCacheSizes["fragmentRegistry.findFragmentSpreads"] */,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fragmentRegistry.js","sourceRoot":"","sources":["../../../src/cache/inmemory/fragmentRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,
|
|
1
|
+
{"version":3,"file":"fragmentRegistry.js","sourceRoot":"","sources":["../../../src/cache/inmemory/fragmentRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["import { WeakCache } from \"@wry/caches\";\nimport type {\n ASTNode,\n DocumentNode,\n FragmentDefinitionNode,\n FragmentSpreadNode,\n} from \"graphql\";\nimport { visit } from \"graphql\";\nimport { wrap } from \"optimism\";\n\nimport { cacheSizes } from \"@apollo/client/utilities\";\nimport type { FragmentMap } from \"@apollo/client/utilities/internal\";\nimport {\n bindCacheKey,\n getFragmentDefinitions,\n} from \"@apollo/client/utilities/internal\";\n\nimport { defaultCacheSizes } from \"../../utilities/caching/sizes.js\";\nexport interface FragmentRegistryAPI {\n register(...fragments: DocumentNode[]): this;\n lookup(fragmentName: string): FragmentDefinitionNode | null;\n transform<D extends DocumentNode>(document: D): D;\n resetCaches(): void;\n}\n\n// As long as createFragmentRegistry is not imported or used, the\n// FragmentRegistry example implementation provided below should not be bundled\n// (by tree-shaking bundlers like Rollup), because the implementation of\n// InMemoryCache refers only to the TypeScript interface FragmentRegistryAPI,\n// never the concrete implementation FragmentRegistry (which is deliberately not\n// exported from this module).\nexport function createFragmentRegistry(\n ...fragments: DocumentNode[]\n): FragmentRegistryAPI {\n return new FragmentRegistry(...fragments);\n}\n\nclass FragmentRegistry implements FragmentRegistryAPI {\n private registry: FragmentMap = {};\n\n // Call `createFragmentRegistry` instead of invoking the\n // FragmentRegistry constructor directly. This reserves the constructor for\n // future configuration of the FragmentRegistry.\n constructor(...fragments: DocumentNode[]) {\n this.resetCaches();\n if (fragments.length) {\n this.register(...fragments);\n }\n }\n\n public register(...fragments: DocumentNode[]): this {\n const definitions = new Map<string, FragmentDefinitionNode>();\n fragments.forEach((doc: DocumentNode) => {\n getFragmentDefinitions(doc).forEach((node) => {\n definitions.set(node.name.value, node);\n });\n });\n\n definitions.forEach((node, name) => {\n if (node !== this.registry[name]) {\n this.registry[name] = node;\n this.invalidate(name);\n }\n });\n\n return this;\n }\n\n // Overridden in the resetCaches method below.\n private invalidate(name: string) {}\n\n public resetCaches() {\n const proto = FragmentRegistry.prototype;\n this.invalidate = (this.lookup = wrap(proto.lookup.bind(this), {\n // This is intentionally an identity function - a string cannot be keyed weakly.\n // This is not a memory leak, as lifetime is bound to the `FragmentRegistry` instance,\n // and max size is configurable.\n makeCacheKey: (arg) => arg,\n max:\n cacheSizes[\"fragmentRegistry.lookup\"] ||\n defaultCacheSizes[\"fragmentRegistry.lookup\"],\n })).dirty; // This dirty function is bound to the wrapped lookup method.\n this.transform = wrap(proto.transform.bind(this), {\n makeCacheKey: bindCacheKey(this),\n cache: WeakCache,\n max:\n cacheSizes[\"fragmentRegistry.transform\"] ||\n defaultCacheSizes[\"fragmentRegistry.transform\"],\n });\n this.findFragmentSpreads = wrap(proto.findFragmentSpreads.bind(this), {\n makeCacheKey: bindCacheKey(this),\n cache: WeakCache,\n max:\n cacheSizes[\"fragmentRegistry.findFragmentSpreads\"] ||\n defaultCacheSizes[\"fragmentRegistry.findFragmentSpreads\"],\n });\n }\n\n /*\n * Note:\n * This method is only memoized so it can serve as a dependency to `transform`,\n * so calling `invalidate` will invalidate cache entries for `transform`.\n */\n public lookup(fragmentName: string): FragmentDefinitionNode | null {\n return this.registry[fragmentName] || null;\n }\n\n public transform<D extends DocumentNode>(document: D): D {\n const defined = new Map<string, FragmentDefinitionNode>();\n getFragmentDefinitions(document).forEach((def) => {\n defined.set(def.name.value, def);\n });\n\n const unbound = new Set<string>();\n const enqueue = (spreadName: string) => {\n if (!defined.has(spreadName)) {\n unbound.add(spreadName);\n }\n };\n\n const enqueueChildSpreads = (node: ASTNode) =>\n Object.keys(this.findFragmentSpreads(node)).forEach(enqueue);\n\n enqueueChildSpreads(document);\n\n const missing: string[] = [];\n const map: FragmentMap = {};\n\n // This Set forEach loop can be extended during iteration by adding\n // additional strings to the unbound set.\n unbound.forEach((fragmentName) => {\n const knownFragmentDef = defined.get(fragmentName);\n if (knownFragmentDef) {\n enqueueChildSpreads((map[fragmentName] = knownFragmentDef));\n } else {\n missing.push(fragmentName);\n const def = this.lookup(fragmentName);\n if (def) {\n enqueueChildSpreads((map[fragmentName] = def));\n }\n }\n });\n\n if (missing.length) {\n const defsToAppend: FragmentDefinitionNode[] = [];\n missing.forEach((name) => {\n const def = map[name];\n if (def) {\n defsToAppend.push(def);\n }\n });\n\n if (defsToAppend.length) {\n document = {\n ...document,\n definitions: document.definitions.concat(defsToAppend),\n };\n }\n }\n\n return document;\n }\n\n public findFragmentSpreads(root: ASTNode): FragmentSpreadMap {\n const spreads: FragmentSpreadMap = {};\n\n visit(root, {\n FragmentSpread(node) {\n spreads[node.name.value] = node;\n },\n });\n\n return spreads;\n }\n}\n\ninterface FragmentSpreadMap {\n [fragmentSpreadName: string]: FragmentSpreadNode;\n}\n"]}
|
|
@@ -43,6 +43,53 @@ export declare class InMemoryCache extends ApolloCache {
|
|
|
43
43
|
reset(options?: Cache.ResetOptions): Promise<void>;
|
|
44
44
|
removeOptimistic(idToRemove: string): void;
|
|
45
45
|
private txCount;
|
|
46
|
+
/**
|
|
47
|
+
* Executes multiple cache operations as a single batch, ensuring that
|
|
48
|
+
* watchers are only notified once after all operations complete. This is
|
|
49
|
+
* useful for improving performance when making multiple cache updates, as it
|
|
50
|
+
* prevents unnecessary re-renders or query refetches between individual
|
|
51
|
+
* operations.
|
|
52
|
+
*
|
|
53
|
+
* The `batch` method supports both optimistic and non-optimistic updates, and
|
|
54
|
+
* provides fine-grained control over which cache layer receives the updates
|
|
55
|
+
* and when watchers are notified.
|
|
56
|
+
*
|
|
57
|
+
* For usage instructions, see [Interacting with cached data: `cache.batch`](https://www.apollographql.com/docs/react/caching/cache-interaction#using-cachebatch).
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
*
|
|
61
|
+
* ```js
|
|
62
|
+
* cache.batch({
|
|
63
|
+
* update(cache) {
|
|
64
|
+
* cache.writeQuery({
|
|
65
|
+
* query: GET_TODOS,
|
|
66
|
+
* data: { todos: updatedTodos },
|
|
67
|
+
* });
|
|
68
|
+
* cache.evict({ id: "Todo:123" });
|
|
69
|
+
* },
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
*
|
|
75
|
+
* ```js
|
|
76
|
+
* // Optimistic update with a custom layer ID
|
|
77
|
+
* cache.batch({
|
|
78
|
+
* optimistic: "add-todo-optimistic",
|
|
79
|
+
* update(cache) {
|
|
80
|
+
* cache.modify({
|
|
81
|
+
* fields: {
|
|
82
|
+
* todos(existing = []) {
|
|
83
|
+
* return [...existing, newTodoRef];
|
|
84
|
+
* },
|
|
85
|
+
* },
|
|
86
|
+
* });
|
|
87
|
+
* },
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @returns The return value of the `update` function.
|
|
92
|
+
*/
|
|
46
93
|
batch<TUpdateResult>(options: Cache.BatchOptions<InMemoryCache, TUpdateResult>): TUpdateResult;
|
|
47
94
|
performTransaction(update: (cache: InMemoryCache) => any, optimisticId?: string | null): any;
|
|
48
95
|
transformDocument(document: DocumentNode): DocumentNode;
|
|
@@ -294,6 +294,53 @@ export class InMemoryCache extends ApolloCache {
|
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
296
|
txCount = 0;
|
|
297
|
+
/**
|
|
298
|
+
* Executes multiple cache operations as a single batch, ensuring that
|
|
299
|
+
* watchers are only notified once after all operations complete. This is
|
|
300
|
+
* useful for improving performance when making multiple cache updates, as it
|
|
301
|
+
* prevents unnecessary re-renders or query refetches between individual
|
|
302
|
+
* operations.
|
|
303
|
+
*
|
|
304
|
+
* The `batch` method supports both optimistic and non-optimistic updates, and
|
|
305
|
+
* provides fine-grained control over which cache layer receives the updates
|
|
306
|
+
* and when watchers are notified.
|
|
307
|
+
*
|
|
308
|
+
* For usage instructions, see [Interacting with cached data: `cache.batch`](https://www.apollographql.com/docs/react/caching/cache-interaction#using-cachebatch).
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
*
|
|
312
|
+
* ```js
|
|
313
|
+
* cache.batch({
|
|
314
|
+
* update(cache) {
|
|
315
|
+
* cache.writeQuery({
|
|
316
|
+
* query: GET_TODOS,
|
|
317
|
+
* data: { todos: updatedTodos },
|
|
318
|
+
* });
|
|
319
|
+
* cache.evict({ id: "Todo:123" });
|
|
320
|
+
* },
|
|
321
|
+
* });
|
|
322
|
+
* ```
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
*
|
|
326
|
+
* ```js
|
|
327
|
+
* // Optimistic update with a custom layer ID
|
|
328
|
+
* cache.batch({
|
|
329
|
+
* optimistic: "add-todo-optimistic",
|
|
330
|
+
* update(cache) {
|
|
331
|
+
* cache.modify({
|
|
332
|
+
* fields: {
|
|
333
|
+
* todos(existing = []) {
|
|
334
|
+
* return [...existing, newTodoRef];
|
|
335
|
+
* },
|
|
336
|
+
* },
|
|
337
|
+
* });
|
|
338
|
+
* },
|
|
339
|
+
* });
|
|
340
|
+
* ```
|
|
341
|
+
*
|
|
342
|
+
* @returns The return value of the `update` function.
|
|
343
|
+
*/
|
|
297
344
|
batch(options) {
|
|
298
345
|
const { update, optimistic = true, removeOptimistic, onWatchUpdated, } = options;
|
|
299
346
|
let updateResult;
|