diff --git a/frontend/javascripts/dashboard/dataset/dataset_collection_context.tsx b/frontend/javascripts/dashboard/dataset/dataset_collection_context.tsx index 86652accef2..a1a221ead86 100644 --- a/frontend/javascripts/dashboard/dataset/dataset_collection_context.tsx +++ b/frontend/javascripts/dashboard/dataset/dataset_collection_context.tsx @@ -25,7 +25,7 @@ import { export type DatasetCollectionContextValue = { datasets: Array; - isLoading: boolean; + isPending: boolean; isChecking: boolean; checkDatasets: () => Promise; fetchDatasets: () => void; @@ -189,10 +189,10 @@ export default function DatasetCollectionContextProvider({ return folderHierarchyQuery.data?.itemById[activeFolderId ?? ""]?.children || []; }; - const isLoading = + const isPending = (globalSearchQuery ? datasetSearchQuery.isFetching - : folderHierarchyQuery.isLoading || + : folderHierarchyQuery.isPending || datasetsInFolderQuery.isFetching || datasetsInFolderQuery.isRefetching) || isMutating; @@ -203,7 +203,7 @@ export default function DatasetCollectionContextProvider({ () => ({ supportsFolders: true as const, datasets, - isLoading, + isPending, fetchDatasets, reloadDataset, updateCachedDataset, @@ -258,7 +258,7 @@ export default function DatasetCollectionContextProvider({ [ isChecking, datasets, - isLoading, + isPending, showCreateFolderPrompt, activeFolderId, mostRecentlyUsedActiveFolderId, diff --git a/frontend/javascripts/dashboard/dataset/queries.tsx b/frontend/javascripts/dashboard/dataset/queries.tsx index f896a9418ab..8dd9645a341 100644 --- a/frontend/javascripts/dashboard/dataset/queries.tsx +++ b/frontend/javascripts/dashboard/dataset/queries.tsx @@ -29,39 +29,35 @@ const FOLDER_TREE_REFETCH_INTERVAL = 30000; export function useFolderQuery(folderId: string | null) { const queryKey = ["folders", folderId]; - return useQuery( + return useQuery({ queryKey, - () => { + queryFn: () => { if (folderId == null) { throw new Error("No folder id provided"); } return getFolder(folderId); }, - { - refetchOnWindowFocus: false, - enabled: folderId != null, - // Avoid default retry delay with exponential back-off - // to shorten the delay after which webKnossos will switch - // to the root folder. - // This is relevant for the case where the current folder - // does not exist, anymore (e.g., was deleted by somebody - // else). - retryDelay: 500, - }, - ); + refetchOnWindowFocus: false, + enabled: folderId != null, + // Avoid default retry delay with exponential back-off + // to shorten the delay after which webKnossos will switch + // to the root folder. + // This is relevant for the case where the current folder + // does not exist, anymore (e.g., was deleted by somebody + // else). + retryDelay: 500, + }); } export function useDatasetQuery(datasetId: string) { const queryKey = ["datasetById", datasetId]; - return useQuery( + return useQuery({ queryKey, - () => { + queryFn: () => { return getDataset(datasetId); }, - { - refetchOnWindowFocus: false, - }, - ); + refetchOnWindowFocus: false, + }); } export function useDatasetSearchQuery( @@ -70,19 +66,17 @@ export function useDatasetSearchQuery( searchRecursively: boolean, ) { const queryKey = ["dataset", "search", query, "in", folderId, "recursive?", searchRecursively]; - return useQuery( + return useQuery({ queryKey, - async () => { + queryFn: async () => { if (query == null || query.length < MINIMUM_SEARCH_QUERY_LENGTH) { return []; } return await getDatasets(null, folderId, query, searchRecursively, SEARCH_RESULTS_LIMIT); }, - { - refetchOnWindowFocus: false, - enabled: query != null, - }, - ); + refetchOnWindowFocus: false, + enabled: query != null, + }); } async function fetchTreeHierarchy() { @@ -91,7 +85,9 @@ async function fetchTreeHierarchy() { } export function useFolderHierarchyQuery() { - return useQuery(["folders"], fetchTreeHierarchy, { + return useQuery({ + queryKey: ["folders"], + queryFn: fetchTreeHierarchy, refetchOnWindowFocus: false, refetchInterval: FOLDER_TREE_REFETCH_INTERVAL, }); @@ -128,9 +124,9 @@ export function useDatasetsInFolderQuery(folderId: string | null) { const queryKey = ["datasetsByFolder", folderId]; const fetchedDatasetsRef = useRef(null); - const queryData = useQuery( + const queryData = useQuery({ queryKey, - () => { + queryFn: () => { if (folderId == null) { // There should always be a folderId, but since hooks cannot // be used within conditionals, we allow folderId to be null. @@ -147,11 +143,9 @@ export function useDatasetsInFolderQuery(folderId: string | null) { return getDatasets(null, folderId); }, - { - refetchOnWindowFocus: false, - enabled: false, - }, - ); + refetchOnWindowFocus: false, + enabled: false, + }); // biome-ignore lint/correctness/useExhaustiveDependencies: Needs investigation whether further dependencies are necessary. useEffect(() => { @@ -267,7 +261,8 @@ export function useCreateFolderMutation() { const queryClient = useQueryClient(); const mutationKey = ["folders"]; - return useMutation(([parentId, name]: [string, string]) => createFolder(parentId, name), { + return useMutation({ + mutationFn: ([parentId, name]: [string, string]) => createFolder(parentId, name), mutationKey, onSuccess: (newFolder: Folder, [parentId]) => { queryClient.setQueryData( @@ -287,7 +282,8 @@ export function useDeleteFolderMutation() { const queryClient = useQueryClient(); const mutationKey = ["folders"]; - return useMutation((id: string) => deleteFolder(id), { + return useMutation({ + mutationFn: (id: string) => deleteFolder(id), mutationKey, onSuccess: (deletedId) => { queryClient.setQueryData( @@ -307,7 +303,8 @@ export function useUpdateFolderMutation() { const queryClient = useQueryClient(); const mutationKey = ["folders"]; - return useMutation((folder: FolderUpdater) => updateFolder(folder), { + return useMutation({ + mutationFn: (folder: FolderUpdater) => updateFolder(folder), mutationKey, onSuccess: (updatedFolder) => { queryClient.setQueryData( @@ -347,36 +344,34 @@ export function useMoveFolderMutation() { ), ); - return useMutation( - ([folderId, newParentId]: [string, string]) => moveFolder(folderId, newParentId), - { - mutationKey, - onMutate: ([folderId, newParentId]) => { - // Optimistically update the folder with the new parent. - const previousFolders = queryClient.getQueryData(mutationKey); - queryClient.setQueryData(mutationKey, updater(folderId, newParentId)); - return { - previousFolders, - }; - }, - onSuccess: (updatedFolder, [folderId, newParentId]) => { - // Use the returned updatedFolder to update the query data - queryClient.setQueryData(mutationKey, updater(updatedFolder.id, newParentId)); - queryClient.setQueryData(["folders", folderId], () => updatedFolder); - }, - onError: (err: any, _params, context) => { - // Restore the old folder tree. Note that without the optimistic update - // and the data reversion here, the sidebar would still show the (incorrectly) - // moved folder, because the component does its own kind of - // optimistic mutation by updating its state immediately when dragging a folder. - handleGenericError(err, "Could not update folder. Check the console for details"); - - if (context) { - queryClient.setQueryData(mutationKey, context.previousFolders); - } - }, + return useMutation({ + mutationFn: ([folderId, newParentId]: [string, string]) => moveFolder(folderId, newParentId), + mutationKey, + onMutate: ([folderId, newParentId]) => { + // Optimistically update the folder with the new parent. + const previousFolders = queryClient.getQueryData(mutationKey); + queryClient.setQueryData(mutationKey, updater(folderId, newParentId)); + return { + previousFolders, + }; }, - ); + onSuccess: (updatedFolder, [folderId, newParentId]) => { + // Use the returned updatedFolder to update the query data + queryClient.setQueryData(mutationKey, updater(updatedFolder.id, newParentId)); + queryClient.setQueryData(["folders", folderId], () => updatedFolder); + }, + onError: (err: any, _params, context) => { + // Restore the old folder tree. Note that without the optimistic update + // and the data reversion here, the sidebar would still show the (incorrectly) + // moved folder, because the component does its own kind of + // optimistic mutation by updating its state immediately when dragging a folder. + handleGenericError(err, "Could not update folder. Check the console for details"); + + if (context) { + queryClient.setQueryData(mutationKey, context.previousFolders); + } + }, + }); } export function useUpdateDatasetMutation(folderId: string | null) { @@ -388,8 +383,8 @@ export function useUpdateDatasetMutation(folderId: string | null) { const queryClient = useQueryClient(); const mutationKey = ["datasetsByFolder", folderId]; - return useMutation( - (params: [string, DatasetUpdater] | string) => { + return useMutation({ + mutationFn: (params: [string, DatasetUpdater] | string) => { // If a APIDatasetId is provided, simply refetch the dataset // without any mutation so that it gets reloaded effectively. if (Array.isArray(params)) { @@ -399,64 +394,62 @@ export function useUpdateDatasetMutation(folderId: string | null) { const datasetId = params; return getDataset(datasetId); }, - { - mutationKey, - onSuccess: (updatedDataset: APIDataset) => { - queryClient.setQueryData(mutationKey, (oldItems: APIDatasetCompact[] | undefined) => - (oldItems || []) - .map((oldDataset: APIDatasetCompact) => { - return oldDataset.id === updatedDataset.id - ? // Don't update lastUsedByUser, since this can lead to annoying reorderings in the table. - convertDatasetToCompact({ - ...updatedDataset, - lastUsedByUser: oldDataset.lastUsedByUser, - }) - : oldDataset; - }) - .filter((dataset: APIDatasetCompact) => dataset.folderId === folderId), + mutationKey, + onSuccess: (updatedDataset: APIDataset) => { + queryClient.setQueryData(mutationKey, (oldItems: APIDatasetCompact[] | undefined) => + (oldItems || []) + .map((oldDataset: APIDatasetCompact) => { + return oldDataset.id === updatedDataset.id + ? // Don't update lastUsedByUser, since this can lead to annoying reorderings in the table. + convertDatasetToCompact({ + ...updatedDataset, + lastUsedByUser: oldDataset.lastUsedByUser, + }) + : oldDataset; + }) + .filter((dataset: APIDatasetCompact) => dataset.folderId === folderId), + ); + // Also update the cached dataset under the key "datasetById". + queryClient.setQueryData(["datasetById", updatedDataset.id], updatedDataset); + const targetFolderId = updatedDataset.folderId; + if (targetFolderId !== folderId) { + // The dataset was moved to another folder. Add the dataset to that target folder + queryClient.setQueryData( + ["datasetsByFolder", targetFolderId], + (oldItems: APIDatasetCompact[] | undefined) => { + if (oldItems == null) { + // Don't update the query data, if it doesn't exist, yet. + // Otherwise, this would lead to weird intermediate states + // (i.e., moving a dataset to folder X and switching to X + // will only show the moved dataset and a spinner; when loading + // has finished, the page will be complete). + return undefined; + } + return ( + oldItems + // The dataset shouldn't be in oldItems, but if it should be + // for some reason (e.g., a bug), we filter it away to avoid + // duplicates. + .filter((el) => el.id !== updatedDataset.id) + .concat([convertDatasetToCompact(updatedDataset)]) + ); + }, ); - // Also update the cached dataset under the key "datasetById". - queryClient.setQueryData(["datasetById", updatedDataset.id], updatedDataset); - const targetFolderId = updatedDataset.folderId; - if (targetFolderId !== folderId) { - // The dataset was moved to another folder. Add the dataset to that target folder - queryClient.setQueryData( - ["datasetsByFolder", targetFolderId], - (oldItems: APIDatasetCompact[] | undefined) => { - if (oldItems == null) { - // Don't update the query data, if it doesn't exist, yet. - // Otherwise, this would lead to weird intermediate states - // (i.e., moving a dataset to folder X and switching to X - // will only show the moved dataset and a spinner; when loading - // has finished, the page will be complete). - return undefined; - } - return ( - oldItems - // The dataset shouldn't be in oldItems, but if it should be - // for some reason (e.g., a bug), we filter it away to avoid - // duplicates. - .filter((el) => el.id !== updatedDataset.id) - .concat([convertDatasetToCompact(updatedDataset)]) - ); - }, - ); - } - // Invalidate all search results so that outdated data won't be shown. - // We could also update the dataset instances in the cache, but this can - // get complex quite fast. Mainly because the mutation of a dataset can affect - // whether it will be found by a search (e.g., when a dataset is moved to another - // folder). - // Simply invalidating the search should be a clean solution for now. - queryClient.invalidateQueries({ - queryKey: ["dataset", "search"], - }); - }, - onError: (err: any) => { - handleGenericError(err, "Could not update dataset."); - }, + } + // Invalidate all search results so that outdated data won't be shown. + // We could also update the dataset instances in the cache, but this can + // get complex quite fast. Mainly because the mutation of a dataset can affect + // whether it will be found by a search (e.g., when a dataset is moved to another + // folder). + // Simply invalidating the search should be a clean solution for now. + queryClient.invalidateQueries({ + queryKey: ["dataset", "search"], + }); }, - ); + onError: (err: any) => { + handleGenericError(err, "Could not update dataset."); + }, + }); } function diffDatasets( diff --git a/frontend/javascripts/dashboard/folders/details_sidebar.tsx b/frontend/javascripts/dashboard/folders/details_sidebar.tsx index c40e3a14b0d..31b445261be 100644 --- a/frontend/javascripts/dashboard/folders/details_sidebar.tsx +++ b/frontend/javascripts/dashboard/folders/details_sidebar.tsx @@ -93,13 +93,11 @@ function DatasetDetails({ selectedDataset }: { selectedDataset: APIDatasetCompac const context = useDatasetCollectionContext(); const { data: fullDataset, isFetching } = useDatasetQuery(selectedDataset.id); const activeUser = useWkSelector((state) => state.activeUser); - const { data: owningOrganization } = useQuery( - ["organizations", selectedDataset.owningOrganization], - () => getOrganization(selectedDataset.owningOrganization), - { - refetchOnWindowFocus: false, - }, - ); + const { data: owningOrganization } = useQuery({ + queryKey: ["organizations", selectedDataset.owningOrganization], + queryFn: () => getOrganization(selectedDataset.owningOrganization), + refetchOnWindowFocus: false, + }); const owningOrganizationName = owningOrganization?.name; const renderOrganization = () => { @@ -203,7 +201,6 @@ function DatasetDetails({ selectedDataset }: { selectedDataset: APIDatasetCompac )} - {fullDataset?.usedStorageBytes && fullDataset.usedStorageBytes > 10000 ? (
Used Storage
diff --git a/frontend/javascripts/main.tsx b/frontend/javascripts/main.tsx index 78ff9ad542b..c1bc5f7a376 100644 --- a/frontend/javascripts/main.tsx +++ b/frontend/javascripts/main.tsx @@ -5,9 +5,9 @@ import { Provider } from "react-redux"; import { warnIfEmailIsUnverified } from "viewer/model/sagas/user_saga"; import UnthrottledStore, { startSaga } from "viewer/store"; -import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { persistQueryClient } from "@tanstack/react-query-persist-client"; +import { createAsyncStoragePersister } from "@tanstack/query-async-storage-persister"; +import { QueryClient } from "@tanstack/react-query"; +import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"; import { checkAnyOrganizationExists, getActiveUser, getOrganization } from "admin/rest_api"; import ErrorBoundary from "components/error_boundary"; import { RootForFastTooltips } from "components/fast_tooltip"; @@ -41,12 +41,12 @@ startSaga(warnIfEmailIsUnverified); const reactQueryClient = new QueryClient({ defaultOptions: { queries: { - cacheTime: Number.POSITIVE_INFINITY, + gcTime: Number.POSITIVE_INFINITY, }, }, }); -const localStoragePersister = createSyncStoragePersister({ +const localStoragePersister = createAsyncStoragePersister({ storage: UserLocalStorage, serialize: (data) => compress(JSON.stringify(data)), deserialize: (data) => JSON.parse(decompress(data) || "{}"), @@ -62,10 +62,6 @@ async function tryToLoadActiveUser() { Store.dispatch(setActiveUserAction(user)); Store.dispatch(setThemeAction(getThemeFromUser(user))); ErrorHandling.setCurrentUser(user); - persistQueryClient({ - queryClient: reactQueryClient, - persister: localStoragePersister, - }); } catch (_e) { // pass } @@ -124,7 +120,10 @@ document.addEventListener("DOMContentLoaded", async () => { {/* @ts-ignore */} - + {/* The DnDProvider is necessary for the TreeHierarchyView. Otherwise, the view may crash in certain conditions. See https://github.com/scalableminds/webknossos/issues/5568 for context. The fix is inspired by: @@ -135,7 +134,7 @@ document.addEventListener("DOMContentLoaded", async () => { - + , ); diff --git a/frontend/javascripts/viewer/view/action-bar/private_links_view.tsx b/frontend/javascripts/viewer/view/action-bar/private_links_view.tsx index a6513c64cd5..91858a38b64 100644 --- a/frontend/javascripts/viewer/view/action-bar/private_links_view.tsx +++ b/frontend/javascripts/viewer/view/action-bar/private_links_view.tsx @@ -44,23 +44,20 @@ import type { ZarrPrivateLink } from "types/api_types"; import { getDataLayers } from "viewer/model/accessors/dataset_accessor"; import { getReadableNameByVolumeTracingId } from "viewer/model/accessors/volumetracing_accessor"; -// TODO Remove explicit (error) type declaration when updating to tanstack/query >= 5 -// https://github.com/TanStack/query/pull/4706 function useLinksQuery(annotationId: string) { - return useQuery( - ["links", annotationId], - () => getPrivateLinksByAnnotation(annotationId), - { - refetchOnWindowFocus: false, - }, - ); + return useQuery({ + queryKey: ["links", annotationId], + queryFn: () => getPrivateLinksByAnnotation(annotationId), + refetchOnWindowFocus: false, + }); } function useCreateLinkMutation(annotationId: string) { const queryClient = useQueryClient(); const mutationKey = ["links", annotationId]; - return useMutation(createPrivateLink, { + return useMutation({ + mutationFn: createPrivateLink, mutationKey, onSuccess: (newLink) => { queryClient.setQueryData(mutationKey, (oldItems: ZarrPrivateLink[] | undefined) => @@ -77,11 +74,14 @@ function useUpdatePrivateLink(annotationId: string) { const queryClient = useQueryClient(); const mutationKey = ["links", annotationId]; - return useMutation(updatePrivateLink, { + return useMutation({ + mutationFn: updatePrivateLink, mutationKey, onMutate: async (updatedLinkItem) => { // Cancel any outgoing refetches (so they don't overwrite our optimistic update) - await queryClient.cancelQueries(mutationKey); + await queryClient.cancelQueries({ + queryKey: mutationKey, + }); // Snapshot the previous value const previousLink = queryClient.getQueryData(mutationKey); @@ -109,11 +109,14 @@ function useDeleteLinkMutation(annotationId: string) { const mutationKey = ["links", annotationId]; - return useMutation(deletePrivateLink, { + return useMutation({ + mutationFn: deletePrivateLink, mutationKey, onMutate: async (linkIdToDelete) => { // Cancel any outgoing refetches (so they don't overwrite our optimistic update) - await queryClient.cancelQueries(mutationKey); + await queryClient.cancelQueries({ + queryKey: mutationKey, + }); // Snapshot the previous value const previousLinks = queryClient.getQueryData(mutationKey); @@ -323,7 +326,7 @@ function HumanizedDuration({ expirationDate }: { expirationDate: dayjs.Dayjs }) } function PrivateLinksView({ annotationId }: { annotationId: string }) { - const { error, data: links, isLoading } = useLinksQuery(annotationId); + const { error, data: links, isPending } = useLinksQuery(annotationId); const createLinkMutation = useCreateLinkMutation(annotationId); const deleteMutation = useDeleteLinkMutation(annotationId); @@ -370,7 +373,7 @@ function PrivateLinksView({ annotationId }: { annotationId: string }) { regardless of other sharing settings.
- {isLoading || links == null ? ( + {isPending || links == null ? (
0; return ( diff --git a/frontend/javascripts/viewer/view/version_list.tsx b/frontend/javascripts/viewer/view/version_list.tsx index 3c022d4a133..6ed47420dd8 100644 --- a/frontend/javascripts/viewer/view/version_list.tsx +++ b/frontend/javascripts/viewer/view/version_list.tsx @@ -254,7 +254,9 @@ function InnerVersionList(props: Props & { newestVersion: number; initialAllowUp // is loaded from scratch. This is important since the loaded page numbers // are relative to the base version. If the version of the tracing changed, // old pages are not valid anymore. - queryClient.removeQueries(queryKey); + queryClient.removeQueries({ + queryKey: queryKey, + }); // Will be set back by handleRestoreVersion or handleCloseRestoreView Store.dispatch(setAnnotationAllowUpdateAction(false)); }); @@ -269,9 +271,12 @@ function InnerVersionList(props: Props & { newestVersion: number; initialAllowUp hasPreviousPage, fetchPreviousPage, isFetchingPreviousPage, - } = useInfiniteQuery(queryKey, fetchPaginatedVersions, { + } = useInfiniteQuery({ + queryKey, + queryFn: fetchPaginatedVersions, refetchOnWindowFocus: false, staleTime: Number.POSITIVE_INFINITY, + initialPageParam: 0, getNextPageParam: (lastPage) => lastPage.nextPage, getPreviousPageParam: (lastPage) => lastPage.previousPage, }); diff --git a/package.json b/package.json index f05b85c579b..06698867e72 100644 --- a/package.json +++ b/package.json @@ -128,9 +128,9 @@ "@fortawesome/fontawesome-free": "^5.15.4", "@rehooks/document-title": "^1.0.2", "@scalableminds/prop-types": "^15.8.1", - "@tanstack/query-sync-storage-persister": "4.36.1", - "@tanstack/react-query": "^4.36.1", - "@tanstack/react-query-persist-client": "4.36.1", + "@tanstack/query-async-storage-persister": "^5.83.0", + "@tanstack/react-query": "^5.83.0", + "@tanstack/react-query-persist-client": "^5.83.0", "@zip.js/zip.js": "^2.7.32", "ansi-to-react": "^6.1.6", "antd": "5.22", diff --git a/yarn.lock b/yarn.lock index 66e8b613221..a8d3fede002 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2359,58 +2359,51 @@ __metadata: languageName: node linkType: hard -"@tanstack/query-core@npm:4.36.1": - version: 4.36.1 - resolution: "@tanstack/query-core@npm:4.36.1" - checksum: 10c0/f286529dbd4c9cdb237ef0bfa72d785c74b5d0958290e8d85c343043ba7be4bbc6cb771167d8c13ca12bd4f37412a3d8b69331f57daa375b2071fd4752aed66a +"@tanstack/query-async-storage-persister@npm:^5.83.0": + version: 5.83.0 + resolution: "@tanstack/query-async-storage-persister@npm:5.83.0" + dependencies: + "@tanstack/query-persist-client-core": "npm:5.83.0" + checksum: 10c0/c6de0ed54a9e17ccf1c1715847bb46dfd23f63f1ef0fb02d3b57f51527b6907a6e918e4751e51f5972681fec006b428f77b85e06edd8e00f1785b5c23b538eb4 languageName: node linkType: hard -"@tanstack/query-persist-client-core@npm:4.36.1": - version: 4.36.1 - resolution: "@tanstack/query-persist-client-core@npm:4.36.1" - dependencies: - "@tanstack/query-core": "npm:4.36.1" - checksum: 10c0/e1c623cf1d43560fcf2f4f8489f8dbae35172c13d563da63c0db9e18937fb55f157a8b2c94011e30ffb1d6f2f40a1cb60dcebe2c9ef2931c0d2e5ca377a28cd8 +"@tanstack/query-core@npm:5.83.0": + version: 5.83.0 + resolution: "@tanstack/query-core@npm:5.83.0" + checksum: 10c0/e6dc480bc99eaca552a9ad65423788b60368cf99308681252fc7dbe42a3f2c1c978db0d3471cc3349b9112cfb4d967ace4e192a1d7e987e30c5c1ff74809c77c languageName: node linkType: hard -"@tanstack/query-sync-storage-persister@npm:4.36.1": - version: 4.36.1 - resolution: "@tanstack/query-sync-storage-persister@npm:4.36.1" +"@tanstack/query-persist-client-core@npm:5.83.0": + version: 5.83.0 + resolution: "@tanstack/query-persist-client-core@npm:5.83.0" dependencies: - "@tanstack/query-persist-client-core": "npm:4.36.1" - checksum: 10c0/ae2d71f59d57d07cf3f96402d01e3b51fa9516cb3e7f2a33787af8d3f8eb56d206b9ca474033afc72dd74badbf8773f8799ab757ace8577f446542407c2850d1 + "@tanstack/query-core": "npm:5.83.0" + checksum: 10c0/70cd08f9aafff2c6fe0ec517dca118aeb3975a96576761d60c43a925839ba75758c1cb61cbeaede21f6471d6be0195d4a5500574f8ca37b0aee25f17d33762a3 languageName: node linkType: hard -"@tanstack/react-query-persist-client@npm:4.36.1": - version: 4.36.1 - resolution: "@tanstack/react-query-persist-client@npm:4.36.1" +"@tanstack/react-query-persist-client@npm:^5.83.0": + version: 5.83.0 + resolution: "@tanstack/react-query-persist-client@npm:5.83.0" dependencies: - "@tanstack/query-persist-client-core": "npm:4.36.1" + "@tanstack/query-persist-client-core": "npm:5.83.0" peerDependencies: - "@tanstack/react-query": ^4.36.1 - checksum: 10c0/a4bdca1ac7d0852f28b3c00a8e5d061be9f54d0d81254cc006e165b86cc514af759f017261ad83f2c76cd404381223627f52e6def1d0814fd7da13fee14f64ff + "@tanstack/react-query": ^5.83.0 + react: ^18 || ^19 + checksum: 10c0/7e14c5f6d83b8556abf14b72586768a6b7f6057a6e3dc4a0f5bbfd7e58b3141a15c049dddd323223c3beb7dac54412b6b9121a954c4e7a95dafc0c76a4bc11f9 languageName: node linkType: hard -"@tanstack/react-query@npm:^4.36.1": - version: 4.36.1 - resolution: "@tanstack/react-query@npm:4.36.1" +"@tanstack/react-query@npm:^5.83.0": + version: 5.83.0 + resolution: "@tanstack/react-query@npm:5.83.0" dependencies: - "@tanstack/query-core": "npm:4.36.1" - use-sync-external-store: "npm:^1.2.0" + "@tanstack/query-core": "npm:5.83.0" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-native: "*" - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - checksum: 10c0/15d9c98269d52fbdd49f4eb4b077b5d70346f904ea2ae51fd0400949d731afde658919a1143dd849fb50d4c5b6d0ab072e7b313a098ef316dd1c24089653f626 + react: ^18 || ^19 + checksum: 10c0/883229f9219ca906a54d7caafd44d59b57db5dbe87e954f8a7027f460e9f8b97842dfbd0d676dc3111d577baf312c64f6c1fdd67cd1e4b0f0bf574e29670c606 languageName: node linkType: hard @@ -14457,7 +14450,7 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:^1.0.0, use-sync-external-store@npm:^1.2.0": +"use-sync-external-store@npm:^1.0.0": version: 1.2.2 resolution: "use-sync-external-store@npm:1.2.2" peerDependencies: @@ -14873,9 +14866,9 @@ __metadata: "@rehooks/document-title": "npm:^1.0.2" "@scalableminds/prop-types": "npm:^15.8.1" "@shaderfrog/glsl-parser": "npm:^0.3.0" - "@tanstack/query-sync-storage-persister": "npm:4.36.1" - "@tanstack/react-query": "npm:^4.36.1" - "@tanstack/react-query-persist-client": "npm:4.36.1" + "@tanstack/query-async-storage-persister": "npm:^5.83.0" + "@tanstack/react-query": "npm:^5.83.0" + "@tanstack/react-query-persist-client": "npm:^5.83.0" "@types/color-hash": "npm:^1.0.2" "@types/cwise": "npm:^1.0.4" "@types/dagre": "npm:^0.7.48"