aboutsummaryrefslogtreecommitdiffstats
path: root/packages/shared-react
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2026-02-01 12:29:54 +0000
committerGitHub <noreply@github.com>2026-02-01 12:29:54 +0000
commit65f6e83f11c82b0ec762e11f3392a80e614ee69a (patch)
tree945d8d73122f07fe6a77c2bd3ac9db566939ba3b /packages/shared-react
parente516a525bca6f319a2f003e9677624e968b277bf (diff)
downloadkarakeep-65f6e83f11c82b0ec762e11f3392a80e614ee69a.tar.zst
refactor: migrate trpc to the new react query integration mode (#2438)
* refactor: migrate trpc to the new react query integration mode * more fixes * more migrations * upgrade trpc client
Diffstat (limited to 'packages/shared-react')
-rw-r--r--packages/shared-react/hooks/assets.ts99
-rw-r--r--packages/shared-react/hooks/bookmarks.ts250
-rw-r--r--packages/shared-react/hooks/highlights.ts93
-rw-r--r--packages/shared-react/hooks/lists.ts196
-rw-r--r--packages/shared-react/hooks/reader-settings.tsx49
-rw-r--r--packages/shared-react/hooks/rules.ts69
-rw-r--r--packages/shared-react/hooks/tags.ts203
-rw-r--r--packages/shared-react/hooks/users.ts56
-rw-r--r--packages/shared-react/package.json3
-rw-r--r--packages/shared-react/providers/trpc-provider.tsx18
-rw-r--r--packages/shared-react/trpc.ts4
11 files changed, 630 insertions, 410 deletions
diff --git a/packages/shared-react/hooks/assets.ts b/packages/shared-react/hooks/assets.ts
index 5367e97c..8be21304 100644
--- a/packages/shared-react/hooks/assets.ts
+++ b/packages/shared-react/hooks/assets.ts
@@ -1,49 +1,74 @@
-import { api } from "../trpc";
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+
+import { useTRPC } from "../trpc";
+
+type TRPCApi = ReturnType<typeof useTRPC>;
export function useAttachBookmarkAsset(
- ...opts: Parameters<typeof api.assets.attachAsset.useMutation>
+ opts?: Parameters<TRPCApi["assets"]["attachAsset"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.assets.attachAsset.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate();
- apiUtils.bookmarks.searchBookmarks.invalidate();
- apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: req.bookmarkId });
- apiUtils.assets.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.assets.attachAsset.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.bookmarks.getBookmarks.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.searchBookmarks.pathFilter(),
+ );
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmark.queryFilter({ bookmarkId: req.bookmarkId }),
+ );
+ queryClient.invalidateQueries(api.assets.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useReplaceBookmarkAsset(
- ...opts: Parameters<typeof api.assets.replaceAsset.useMutation>
+ opts?: Parameters<TRPCApi["assets"]["replaceAsset"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.assets.replaceAsset.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate();
- apiUtils.bookmarks.searchBookmarks.invalidate();
- apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: req.bookmarkId });
- apiUtils.assets.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.assets.replaceAsset.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.bookmarks.getBookmarks.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.searchBookmarks.pathFilter(),
+ );
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmark.queryFilter({ bookmarkId: req.bookmarkId }),
+ );
+ queryClient.invalidateQueries(api.assets.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useDetachBookmarkAsset(
- ...opts: Parameters<typeof api.assets.detachAsset.useMutation>
+ opts?: Parameters<TRPCApi["assets"]["detachAsset"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.assets.detachAsset.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate();
- apiUtils.bookmarks.searchBookmarks.invalidate();
- apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: req.bookmarkId });
- apiUtils.assets.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.assets.detachAsset.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.bookmarks.getBookmarks.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.searchBookmarks.pathFilter(),
+ );
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmark.queryFilter({ bookmarkId: req.bookmarkId }),
+ );
+ queryClient.invalidateQueries(api.assets.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
diff --git a/packages/shared-react/hooks/bookmarks.ts b/packages/shared-react/hooks/bookmarks.ts
index aea2d185..6ff75d7e 100644
--- a/packages/shared-react/hooks/bookmarks.ts
+++ b/packages/shared-react/hooks/bookmarks.ts
@@ -1,132 +1,196 @@
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+
import { getBookmarkRefreshInterval } from "@karakeep/shared/utils/bookmarkUtils";
-import { api } from "../trpc";
+import { useTRPC } from "../trpc";
import { useBookmarkGridContext } from "./bookmark-grid-context";
import { useAddBookmarkToList } from "./lists";
+type TRPCApi = ReturnType<typeof useTRPC>;
+
export function useAutoRefreshingBookmarkQuery(
- input: Parameters<typeof api.bookmarks.getBookmark.useQuery>[0],
+ input: Parameters<TRPCApi["bookmarks"]["getBookmark"]["queryOptions"]>[0],
) {
- return api.bookmarks.getBookmark.useQuery(input, {
- refetchInterval: (query) => {
- const data = query.state.data;
- if (!data) {
- return false;
- }
- return getBookmarkRefreshInterval(data);
- },
- });
+ const api = useTRPC();
+ return useQuery(
+ api.bookmarks.getBookmark.queryOptions(input, {
+ refetchInterval: (query) => {
+ const data = query.state.data;
+ if (!data) {
+ return false;
+ }
+ return getBookmarkRefreshInterval(data);
+ },
+ }),
+ );
}
export function useCreateBookmark(
- ...opts: Parameters<typeof api.bookmarks.createBookmark.useMutation>
+ opts?: Parameters<
+ TRPCApi["bookmarks"]["createBookmark"]["mutationOptions"]
+ >[0],
) {
- const apiUtils = api.useUtils();
- return api.bookmarks.createBookmark.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate();
- apiUtils.bookmarks.searchBookmarks.invalidate();
- apiUtils.lists.stats.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.bookmarks.createBookmark.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.bookmarks.getBookmarks.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.searchBookmarks.pathFilter(),
+ );
+ queryClient.invalidateQueries(api.lists.stats.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useCreateBookmarkWithPostHook(
- ...opts: Parameters<typeof api.bookmarks.createBookmark.useMutation>
+ opts?: Parameters<
+ TRPCApi["bookmarks"]["createBookmark"]["mutationOptions"]
+ >[0],
) {
- const apiUtils = api.useUtils();
+ const api = useTRPC();
+ const queryClient = useQueryClient();
const postCreationCB = useBookmarkPostCreationHook();
- return api.bookmarks.createBookmark.useMutation({
- ...opts[0],
- onSuccess: async (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate();
- apiUtils.bookmarks.searchBookmarks.invalidate();
- await postCreationCB(res.id);
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ return useMutation(
+ api.bookmarks.createBookmark.mutationOptions({
+ ...opts,
+ onSuccess: async (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.bookmarks.getBookmarks.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.searchBookmarks.pathFilter(),
+ );
+ await postCreationCB(res.id);
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useDeleteBookmark(
- ...opts: Parameters<typeof api.bookmarks.deleteBookmark.useMutation>
+ opts?: Parameters<
+ TRPCApi["bookmarks"]["deleteBookmark"]["mutationOptions"]
+ >[0],
) {
- const apiUtils = api.useUtils();
- return api.bookmarks.deleteBookmark.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate();
- apiUtils.bookmarks.searchBookmarks.invalidate();
- apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: req.bookmarkId });
- apiUtils.lists.stats.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.bookmarks.deleteBookmark.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.bookmarks.getBookmarks.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.searchBookmarks.pathFilter(),
+ );
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmark.queryFilter({ bookmarkId: req.bookmarkId }),
+ );
+ queryClient.invalidateQueries(api.lists.stats.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useUpdateBookmark(
- ...opts: Parameters<typeof api.bookmarks.updateBookmark.useMutation>
+ opts?: Parameters<
+ TRPCApi["bookmarks"]["updateBookmark"]["mutationOptions"]
+ >[0],
) {
- const apiUtils = api.useUtils();
- return api.bookmarks.updateBookmark.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate();
- apiUtils.bookmarks.searchBookmarks.invalidate();
- apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: req.bookmarkId });
- apiUtils.lists.stats.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.bookmarks.updateBookmark.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.bookmarks.getBookmarks.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.searchBookmarks.pathFilter(),
+ );
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmark.queryFilter({ bookmarkId: req.bookmarkId }),
+ );
+ queryClient.invalidateQueries(api.lists.stats.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useSummarizeBookmark(
- ...opts: Parameters<typeof api.bookmarks.summarizeBookmark.useMutation>
+ opts?: Parameters<
+ TRPCApi["bookmarks"]["summarizeBookmark"]["mutationOptions"]
+ >[0],
) {
- const apiUtils = api.useUtils();
- return api.bookmarks.summarizeBookmark.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate();
- apiUtils.bookmarks.searchBookmarks.invalidate();
- apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: req.bookmarkId });
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.bookmarks.summarizeBookmark.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.bookmarks.getBookmarks.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.searchBookmarks.pathFilter(),
+ );
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmark.queryFilter({ bookmarkId: req.bookmarkId }),
+ );
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useRecrawlBookmark(
- ...opts: Parameters<typeof api.bookmarks.recrawlBookmark.useMutation>
+ opts?: Parameters<
+ TRPCApi["bookmarks"]["recrawlBookmark"]["mutationOptions"]
+ >[0],
) {
- const apiUtils = api.useUtils();
- return api.bookmarks.recrawlBookmark.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: req.bookmarkId });
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.bookmarks.recrawlBookmark.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmark.queryFilter({ bookmarkId: req.bookmarkId }),
+ );
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useUpdateBookmarkTags(
- ...opts: Parameters<typeof api.bookmarks.updateTags.useMutation>
+ opts?: Parameters<TRPCApi["bookmarks"]["updateTags"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.bookmarks.updateTags.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmark.invalidate({ bookmarkId: req.bookmarkId });
-
- [...res.attached, ...res.detached].forEach((id) => {
- apiUtils.tags.get.invalidate({ tagId: id });
- apiUtils.bookmarks.getBookmarks.invalidate({ tagId: id });
- });
- apiUtils.tags.list.invalidate();
- apiUtils.lists.stats.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.bookmarks.updateTags.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmark.queryFilter({ bookmarkId: req.bookmarkId }),
+ );
+
+ [...res.attached, ...res.detached].forEach((id) => {
+ queryClient.invalidateQueries(
+ api.tags.get.queryFilter({ tagId: id }),
+ );
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmarks.queryFilter({ tagId: id }),
+ );
+ });
+ queryClient.invalidateQueries(api.tags.list.pathFilter());
+ queryClient.invalidateQueries(api.lists.stats.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
/**
diff --git a/packages/shared-react/hooks/highlights.ts b/packages/shared-react/hooks/highlights.ts
index e642f878..3f6a6e01 100644
--- a/packages/shared-react/hooks/highlights.ts
+++ b/packages/shared-react/hooks/highlights.ts
@@ -1,49 +1,68 @@
-import { api } from "../trpc";
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+
+import { useTRPC } from "../trpc";
+
+type TRPCApi = ReturnType<typeof useTRPC>;
export function useCreateHighlight(
- ...opts: Parameters<typeof api.highlights.create.useMutation>
+ opts?: Parameters<TRPCApi["highlights"]["create"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.highlights.create.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.highlights.getForBookmark.invalidate({
- bookmarkId: req.bookmarkId,
- });
- apiUtils.highlights.getAll.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.highlights.create.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(
+ api.highlights.getForBookmark.queryFilter({
+ bookmarkId: req.bookmarkId,
+ }),
+ );
+ queryClient.invalidateQueries(api.highlights.getAll.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useUpdateHighlight(
- ...opts: Parameters<typeof api.highlights.update.useMutation>
+ opts?: Parameters<TRPCApi["highlights"]["update"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.highlights.update.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.highlights.getForBookmark.invalidate({
- bookmarkId: res.bookmarkId,
- });
- apiUtils.highlights.getAll.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.highlights.update.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(
+ api.highlights.getForBookmark.queryFilter({
+ bookmarkId: res.bookmarkId,
+ }),
+ );
+ queryClient.invalidateQueries(api.highlights.getAll.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useDeleteHighlight(
- ...opts: Parameters<typeof api.highlights.delete.useMutation>
+ opts?: Parameters<TRPCApi["highlights"]["delete"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.highlights.delete.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.highlights.getForBookmark.invalidate({
- bookmarkId: res.bookmarkId,
- });
- apiUtils.highlights.getAll.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.highlights.delete.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(
+ api.highlights.getForBookmark.queryFilter({
+ bookmarkId: res.bookmarkId,
+ }),
+ );
+ queryClient.invalidateQueries(api.highlights.getAll.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
diff --git a/packages/shared-react/hooks/lists.ts b/packages/shared-react/hooks/lists.ts
index d269efe3..231e43a7 100644
--- a/packages/shared-react/hooks/lists.ts
+++ b/packages/shared-react/hooks/lists.ts
@@ -1,113 +1,155 @@
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+
import { ZBookmarkList } from "@karakeep/shared/types/lists";
import {
listsToTree,
ZBookmarkListRoot,
} from "@karakeep/shared/utils/listUtils";
-import { api } from "../trpc";
+import { useTRPC } from "../trpc";
+
+type TRPCApi = ReturnType<typeof useTRPC>;
export function useCreateBookmarkList(
- ...opts: Parameters<typeof api.lists.create.useMutation>
+ opts?: Parameters<TRPCApi["lists"]["create"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.lists.create.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.lists.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.lists.create.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.lists.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useEditBookmarkList(
- ...opts: Parameters<typeof api.lists.edit.useMutation>
+ opts?: Parameters<TRPCApi["lists"]["edit"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.lists.edit.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.lists.list.invalidate();
- apiUtils.lists.get.invalidate({ listId: req.listId });
- if (res.type === "smart") {
- apiUtils.bookmarks.getBookmarks.invalidate({ listId: req.listId });
- }
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.lists.edit.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.lists.list.pathFilter());
+ queryClient.invalidateQueries(
+ api.lists.get.queryFilter({ listId: req.listId }),
+ );
+ if (res.type === "smart") {
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmarks.queryFilter({ listId: req.listId }),
+ );
+ }
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useMergeLists(
- ...opts: Parameters<typeof api.lists.merge.useMutation>
+ opts?: Parameters<TRPCApi["lists"]["merge"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.lists.merge.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.lists.list.invalidate();
- apiUtils.bookmarks.getBookmarks.invalidate({ listId: req.targetId });
- apiUtils.lists.stats.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.lists.merge.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.lists.list.pathFilter());
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmarks.queryFilter({ listId: req.targetId }),
+ );
+ queryClient.invalidateQueries(api.lists.stats.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useAddBookmarkToList(
- ...opts: Parameters<typeof api.lists.addToList.useMutation>
+ opts?: Parameters<TRPCApi["lists"]["addToList"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.lists.addToList.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate({ listId: req.listId });
- apiUtils.lists.getListsOfBookmark.invalidate({
- bookmarkId: req.bookmarkId,
- });
- apiUtils.lists.stats.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.lists.addToList.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmarks.queryFilter({ listId: req.listId }),
+ );
+ queryClient.invalidateQueries(
+ api.lists.getListsOfBookmark.queryFilter({
+ bookmarkId: req.bookmarkId,
+ }),
+ );
+ queryClient.invalidateQueries(api.lists.stats.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useRemoveBookmarkFromList(
- ...opts: Parameters<typeof api.lists.removeFromList.useMutation>
+ opts?: Parameters<TRPCApi["lists"]["removeFromList"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.lists.removeFromList.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.bookmarks.getBookmarks.invalidate({ listId: req.listId });
- apiUtils.lists.getListsOfBookmark.invalidate({
- bookmarkId: req.bookmarkId,
- });
- apiUtils.lists.stats.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.lists.removeFromList.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmarks.queryFilter({ listId: req.listId }),
+ );
+ queryClient.invalidateQueries(
+ api.lists.getListsOfBookmark.queryFilter({
+ bookmarkId: req.bookmarkId,
+ }),
+ );
+ queryClient.invalidateQueries(api.lists.stats.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useDeleteBookmarkList(
- ...opts: Parameters<typeof api.lists.delete.useMutation>
+ opts?: Parameters<TRPCApi["lists"]["delete"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.lists.delete.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.lists.list.invalidate();
- apiUtils.lists.get.invalidate({ listId: req.listId });
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.lists.delete.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.lists.list.pathFilter());
+ queryClient.invalidateQueries(
+ api.lists.get.queryFilter({ listId: req.listId }),
+ );
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useBookmarkLists(
- ...opts: Parameters<typeof api.lists.list.useQuery>
+ input?: Parameters<TRPCApi["lists"]["list"]["queryOptions"]>[0],
+ opts?: Parameters<TRPCApi["lists"]["list"]["queryOptions"]>[1],
) {
- return api.lists.list.useQuery(opts[0], {
- ...opts[1],
- select: (data) => {
- return { data: data.lists, ...listsToTree(data.lists) };
- },
- });
+ const api = useTRPC();
+ return useQuery(
+ api.lists.list.queryOptions(input, {
+ ...opts,
+ select: (data) => {
+ return { data: data.lists, ...listsToTree(data.lists) };
+ },
+ }),
+ );
}
export function augmentBookmarkListsWithInitialData(
diff --git a/packages/shared-react/hooks/reader-settings.tsx b/packages/shared-react/hooks/reader-settings.tsx
index 2705a050..7258ebe9 100644
--- a/packages/shared-react/hooks/reader-settings.tsx
+++ b/packages/shared-react/hooks/reader-settings.tsx
@@ -9,6 +9,7 @@ import {
useMemo,
useState,
} from "react";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
READER_DEFAULTS,
@@ -16,7 +17,7 @@ import {
ReaderSettingsPartial,
} from "@karakeep/shared/types/readers";
-import { api } from "../trpc";
+import { useTRPC } from "../trpc";
export interface UseReaderSettingsOptions {
/**
@@ -39,6 +40,7 @@ export interface UseReaderSettingsOptions {
}
export function useReaderSettings(options: UseReaderSettingsOptions) {
+ const api = useTRPC();
const {
getLocalOverrides,
saveLocalOverrides,
@@ -52,8 +54,8 @@ export function useReaderSettings(options: UseReaderSettingsOptions) {
const [pendingServerSave, setPendingServerSave] =
useState<ReaderSettings | null>(null);
- const { data: serverSettings } = api.users.settings.useQuery();
- const apiUtils = api.useUtils();
+ const { data: serverSettings } = useQuery(api.users.settings.queryOptions());
+ const queryClient = useQueryClient();
// Load local overrides on mount
useEffect(() => {
@@ -76,30 +78,33 @@ export function useReaderSettings(options: UseReaderSettingsOptions) {
}
}, [serverSettings, pendingServerSave]);
- const { mutate: updateServerSettings, isPending: isSaving } =
- api.users.updateSettings.useMutation({
+ const { mutate: updateServerSettings, isPending: isSaving } = useMutation(
+ api.users.updateSettings.mutationOptions({
onSettled: async () => {
- await apiUtils.users.settings.refetch();
+ await queryClient.refetchQueries(api.users.settings.pathFilter());
},
- });
+ }),
+ );
// Separate mutation for saving defaults (clears local overrides on success)
const { mutate: saveServerSettings, isPending: isSavingDefaults } =
- api.users.updateSettings.useMutation({
- onSuccess: () => {
- // Clear local and session overrides after successful server save
- setLocalOverrides({});
- saveLocalOverrides({});
- onClearSessionOverrides?.();
- },
- onError: () => {
- // Clear pending state so we don't show values that failed to persist
- setPendingServerSave(null);
- },
- onSettled: async () => {
- await apiUtils.users.settings.refetch();
- },
- });
+ useMutation(
+ api.users.updateSettings.mutationOptions({
+ onSuccess: () => {
+ // Clear local and session overrides after successful server save
+ setLocalOverrides({});
+ saveLocalOverrides({});
+ onClearSessionOverrides?.();
+ },
+ onError: () => {
+ // Clear pending state so we don't show values that failed to persist
+ setPendingServerSave(null);
+ },
+ onSettled: async () => {
+ await queryClient.refetchQueries(api.users.settings.pathFilter());
+ },
+ }),
+ );
// Compute effective settings with precedence: session → local → pendingSave → server → default
const settings: ReaderSettings = useMemo(
diff --git a/packages/shared-react/hooks/rules.ts b/packages/shared-react/hooks/rules.ts
index 8428f883..8bca9d69 100644
--- a/packages/shared-react/hooks/rules.ts
+++ b/packages/shared-react/hooks/rules.ts
@@ -1,40 +1,53 @@
-import { api } from "../trpc";
+import { useMutation, useQueryClient } from "@tanstack/react-query";
+
+import { useTRPC } from "../trpc";
+
+type TRPCApi = ReturnType<typeof useTRPC>;
export function useCreateRule(
- ...opts: Parameters<typeof api.rules.create.useMutation>
+ opts?: Parameters<TRPCApi["rules"]["create"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.rules.create.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.rules.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.rules.create.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.rules.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useUpdateRule(
- ...opts: Parameters<typeof api.rules.update.useMutation>
+ opts?: Parameters<TRPCApi["rules"]["update"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.rules.update.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.rules.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.rules.update.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.rules.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useDeleteRule(
- ...opts: Parameters<typeof api.rules.delete.useMutation>
+ opts?: Parameters<TRPCApi["rules"]["delete"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.rules.delete.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.rules.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.rules.delete.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.rules.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
diff --git a/packages/shared-react/hooks/tags.ts b/packages/shared-react/hooks/tags.ts
index e1e7416f..a616b88a 100644
--- a/packages/shared-react/hooks/tags.ts
+++ b/packages/shared-react/hooks/tags.ts
@@ -1,120 +1,155 @@
-import { keepPreviousData } from "@tanstack/react-query";
+import {
+ keepPreviousData,
+ useInfiniteQuery,
+ useMutation,
+ useQuery,
+ useQueryClient,
+} from "@tanstack/react-query";
import { ZTagListResponse } from "@karakeep/shared/types/tags";
-import { api } from "../trpc";
+import { useTRPC } from "../trpc";
+
+type TRPCApi = ReturnType<typeof useTRPC>;
export function usePaginatedSearchTags(
- input: Parameters<typeof api.tags.list.useInfiniteQuery>[0],
+ input: Parameters<TRPCApi["tags"]["list"]["infiniteQueryOptions"]>[0],
) {
- return api.tags.list.useInfiniteQuery(input, {
- placeholderData: keepPreviousData,
- getNextPageParam: (lastPage) => lastPage.nextCursor,
+ const api = useTRPC();
+ return useInfiniteQuery({
+ ...api.tags.list.infiniteQueryOptions(input, {
+ placeholderData: keepPreviousData,
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
+ gcTime: 60_000,
+ }),
select: (data) => ({
tags: data.pages.flatMap((page) => page.tags),
}),
- gcTime: 60_000,
});
}
-export function useTagAutocomplete<T>(opts: {
+export function useTagAutocomplete<T = ZTagListResponse>(opts: {
nameContains: string;
- select?: (tags: ZTagListResponse) => T;
+ select?: (data: ZTagListResponse) => T;
enabled?: boolean;
}) {
- return api.tags.list.useQuery(
- {
- nameContains: opts.nameContains,
- limit: 50,
- sortBy: opts.nameContains ? "relevance" : "usage",
- },
- {
- select: opts.select,
- placeholderData: keepPreviousData,
- gcTime: opts.nameContains?.length > 0 ? 60_000 : 3_600_000,
- enabled: opts.enabled,
- },
- );
+ const api = useTRPC();
+ return useQuery({
+ ...api.tags.list.queryOptions(
+ {
+ nameContains: opts.nameContains,
+ limit: 50,
+ sortBy: opts.nameContains ? "relevance" : "usage",
+ },
+ {
+ placeholderData: keepPreviousData,
+ gcTime: opts.nameContains?.length > 0 ? 60_000 : 3_600_000,
+ enabled: opts.enabled,
+ },
+ ),
+ select: opts.select,
+ });
}
export function useCreateTag(
- ...opts: Parameters<typeof api.tags.create.useMutation>
+ opts?: Parameters<TRPCApi["tags"]["create"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
-
- return api.tags.create.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.tags.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+
+ return useMutation(
+ api.tags.create.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.tags.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useUpdateTag(
- ...opts: Parameters<typeof api.tags.update.useMutation>
+ opts?: Parameters<TRPCApi["tags"]["update"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
-
- return api.tags.update.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.tags.list.invalidate();
- apiUtils.tags.get.invalidate({ tagId: res.id });
- apiUtils.bookmarks.getBookmarks.invalidate({ tagId: res.id });
-
- // TODO: Maybe we can only look at the cache and invalidate only affected bookmarks
- apiUtils.bookmarks.getBookmark.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+
+ return useMutation(
+ api.tags.update.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.tags.list.pathFilter());
+ queryClient.invalidateQueries(
+ api.tags.get.queryFilter({ tagId: res.id }),
+ );
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmarks.queryFilter({ tagId: res.id }),
+ );
+
+ // TODO: Maybe we can only look at the cache and invalidate only affected bookmarks
+ queryClient.invalidateQueries(api.bookmarks.getBookmark.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useMergeTag(
- ...opts: Parameters<typeof api.tags.merge.useMutation>
+ opts?: Parameters<TRPCApi["tags"]["merge"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
-
- return api.tags.merge.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.tags.list.invalidate();
- [res.mergedIntoTagId, ...res.deletedTags].forEach((tagId) => {
- apiUtils.tags.get.invalidate({ tagId });
- apiUtils.bookmarks.getBookmarks.invalidate({ tagId });
- });
- // TODO: Maybe we can only look at the cache and invalidate only affected bookmarks
- apiUtils.bookmarks.getBookmark.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+
+ return useMutation(
+ api.tags.merge.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.tags.list.pathFilter());
+ [res.mergedIntoTagId, ...res.deletedTags].forEach((tagId) => {
+ queryClient.invalidateQueries(api.tags.get.queryFilter({ tagId }));
+ queryClient.invalidateQueries(
+ api.bookmarks.getBookmarks.queryFilter({ tagId }),
+ );
+ });
+ // TODO: Maybe we can only look at the cache and invalidate only affected bookmarks
+ queryClient.invalidateQueries(api.bookmarks.getBookmark.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useDeleteTag(
- ...opts: Parameters<typeof api.tags.delete.useMutation>
+ opts?: Parameters<TRPCApi["tags"]["delete"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
-
- return api.tags.delete.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.tags.list.invalidate();
- apiUtils.bookmarks.getBookmark.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+
+ return useMutation(
+ api.tags.delete.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.tags.list.pathFilter());
+ queryClient.invalidateQueries(api.bookmarks.getBookmark.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useDeleteUnusedTags(
- ...opts: Parameters<typeof api.tags.deleteUnused.useMutation>
+ opts?: Parameters<TRPCApi["tags"]["deleteUnused"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
-
- return api.tags.deleteUnused.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.tags.list.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+
+ return useMutation(
+ api.tags.deleteUnused.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.tags.list.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
diff --git a/packages/shared-react/hooks/users.ts b/packages/shared-react/hooks/users.ts
index b1909761..221681a4 100644
--- a/packages/shared-react/hooks/users.ts
+++ b/packages/shared-react/hooks/users.ts
@@ -1,37 +1,49 @@
-import { api } from "../trpc";
+import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
+
+import { useTRPC } from "../trpc";
+
+type TRPCApi = ReturnType<typeof useTRPC>;
export function useUpdateUserSettings(
- ...opts: Parameters<typeof api.users.updateSettings.useMutation>
+ opts?: Parameters<TRPCApi["users"]["updateSettings"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.users.updateSettings.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.users.settings.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.users.updateSettings.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.users.settings.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useUpdateUserAvatar(
- ...opts: Parameters<typeof api.users.updateAvatar.useMutation>
+ opts?: Parameters<TRPCApi["users"]["updateAvatar"]["mutationOptions"]>[0],
) {
- const apiUtils = api.useUtils();
- return api.users.updateAvatar.useMutation({
- ...opts[0],
- onSuccess: (res, req, meta, context) => {
- apiUtils.users.whoami.invalidate();
- return opts[0]?.onSuccess?.(res, req, meta, context);
- },
- });
+ const api = useTRPC();
+ const queryClient = useQueryClient();
+ return useMutation(
+ api.users.updateAvatar.mutationOptions({
+ ...opts,
+ onSuccess: (res, req, meta, context) => {
+ queryClient.invalidateQueries(api.users.whoami.pathFilter());
+ return opts?.onSuccess?.(res, req, meta, context);
+ },
+ }),
+ );
}
export function useDeleteAccount(
- ...opts: Parameters<typeof api.users.deleteAccount.useMutation>
+ opts?: Parameters<TRPCApi["users"]["deleteAccount"]["mutationOptions"]>[0],
) {
- return api.users.deleteAccount.useMutation(opts[0]);
+ const api = useTRPC();
+ return useMutation(api.users.deleteAccount.mutationOptions(opts));
}
export function useWhoAmI() {
- return api.users.whoami.useQuery();
+ const api = useTRPC();
+ return useQuery(api.users.whoami.queryOptions());
}
diff --git a/packages/shared-react/package.json b/packages/shared-react/package.json
index cf0539be..ce29a24e 100644
--- a/packages/shared-react/package.json
+++ b/packages/shared-react/package.json
@@ -8,7 +8,8 @@
"@karakeep/shared": "workspace:^0.1.0",
"@karakeep/trpc": "workspace:^0.1.0",
"@tanstack/react-query": "5.90.2",
- "@trpc/client": "^11.4.3",
+ "@trpc/client": "^11.9.0",
+ "@trpc/tanstack-react-query": "^11.9.0",
"superjson": "^2.2.1"
},
"devDependencies": {
diff --git a/packages/shared-react/providers/trpc-provider.tsx b/packages/shared-react/providers/trpc-provider.tsx
index 696bf195..2c41aa11 100644
--- a/packages/shared-react/providers/trpc-provider.tsx
+++ b/packages/shared-react/providers/trpc-provider.tsx
@@ -1,9 +1,11 @@
import { useMemo } from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
-import { httpBatchLink } from "@trpc/client";
+import { createTRPCClient, httpBatchLink } from "@trpc/client";
import superjson from "superjson";
-import { api } from "../trpc";
+import type { AppRouter } from "@karakeep/trpc/routers/_app";
+
+import { TRPCProvider } from "../trpc";
interface Settings {
apiKey?: string;
@@ -12,7 +14,7 @@ interface Settings {
}
function getTRPCClient(settings: Settings) {
- return api.createClient({
+ return createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: `${settings.address}/api/trpc`,
@@ -31,7 +33,7 @@ function getTRPCClient(settings: Settings) {
});
}
-export function TRPCProvider({
+export function TRPCSettingsProvider({
settings,
children,
}: {
@@ -42,8 +44,10 @@ export function TRPCProvider({
const trpcClient = useMemo(() => getTRPCClient(settings), [settings]);
return (
- <api.Provider client={trpcClient} queryClient={queryClient}>
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
- </api.Provider>
+ <QueryClientProvider client={queryClient}>
+ <TRPCProvider trpcClient={trpcClient} queryClient={queryClient}>
+ {children}
+ </TRPCProvider>
+ </QueryClientProvider>
);
}
diff --git a/packages/shared-react/trpc.ts b/packages/shared-react/trpc.ts
index 1478684f..2a36b257 100644
--- a/packages/shared-react/trpc.ts
+++ b/packages/shared-react/trpc.ts
@@ -1,7 +1,7 @@
"use client";
-import { createTRPCReact } from "@trpc/react-query";
+import { createTRPCContext } from "@trpc/tanstack-react-query";
import type { AppRouter } from "@karakeep/trpc/routers/_app";
-export const api = createTRPCReact<AppRouter>();
+export const { TRPCProvider, useTRPC } = createTRPCContext<AppRouter>();