aboutsummaryrefslogtreecommitdiffstats
path: root/apps/browser-extension/src/utils/trpc.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/browser-extension/src/utils/trpc.ts')
-rw-r--r--apps/browser-extension/src/utils/trpc.ts116
1 files changed, 116 insertions, 0 deletions
diff --git a/apps/browser-extension/src/utils/trpc.ts b/apps/browser-extension/src/utils/trpc.ts
index e56968b8..76534bcb 100644
--- a/apps/browser-extension/src/utils/trpc.ts
+++ b/apps/browser-extension/src/utils/trpc.ts
@@ -1,5 +1,121 @@
+import { QueryClient } from "@tanstack/react-query";
+import { persistQueryClient } from "@tanstack/react-query-persist-client";
+import { createTRPCClient, httpBatchLink } from "@trpc/client";
import { createTRPCReact } from "@trpc/react-query";
+import superjson from "superjson";
import type { AppRouter } from "@karakeep/trpc/routers/_app";
+import { getPluginSettings } from "./settings";
+import { createChromeStorage } from "./storagePersister";
+
export const api = createTRPCReact<AppRouter>();
+
+let apiClient: ReturnType<typeof createTRPCClient<AppRouter>> | null = null;
+let queryClient: QueryClient | null = null;
+let currentSettings: {
+ address: string;
+ apiKey: string;
+ badgeCacheExpireMs: number;
+ useBadgeCache: boolean;
+} | null = null;
+
+export async function initializeClients() {
+ const { address, apiKey, badgeCacheExpireMs, useBadgeCache } =
+ await getPluginSettings();
+
+ if (currentSettings) {
+ const addressChanged = currentSettings.address !== address;
+ const apiKeyChanged = currentSettings.apiKey !== apiKey;
+ const cacheTimeChanged =
+ currentSettings.badgeCacheExpireMs !== badgeCacheExpireMs;
+ const useBadgeCacheChanged =
+ currentSettings.useBadgeCache !== useBadgeCache;
+
+ if (!address || !apiKey) {
+ // Invalid configuration, clean
+ const persisterForCleanup = createChromeStorage();
+ await persisterForCleanup.removeClient();
+ cleanupApiClient();
+ return;
+ }
+
+ if (addressChanged || apiKeyChanged) {
+ // Switch context completely → discard the old instance and wipe persisted cache
+ const persisterForCleanup = createChromeStorage();
+ await persisterForCleanup.removeClient();
+ cleanupApiClient();
+ } else if ((cacheTimeChanged || useBadgeCacheChanged) && queryClient) {
+ // Change the cache policy only → Clean up the data, but reuse the instance
+ queryClient.clear();
+ }
+
+ // If there is already existing and there is no major change in settings, reuse it
+ if (
+ queryClient &&
+ apiClient &&
+ currentSettings &&
+ !addressChanged &&
+ !apiKeyChanged &&
+ !cacheTimeChanged &&
+ !useBadgeCacheChanged
+ ) {
+ return;
+ }
+ }
+
+ if (address && apiKey) {
+ // Store current settings
+ currentSettings = { address, apiKey, badgeCacheExpireMs, useBadgeCache };
+
+ // Create new QueryClient with updated settings
+ queryClient = new QueryClient();
+
+ const persister = createChromeStorage();
+ if (useBadgeCache) {
+ persistQueryClient({
+ queryClient,
+ persister,
+ // Avoid restoring very old data and bust on policy changes
+ maxAge: badgeCacheExpireMs * 2,
+ buster: `badge:${address}:${badgeCacheExpireMs}`,
+ });
+ } else {
+ // Ensure disk cache is cleared when caching is disabled
+ await persister.removeClient();
+ }
+
+ apiClient = createTRPCClient<AppRouter>({
+ links: [
+ httpBatchLink({
+ url: `${address}/api/trpc`,
+ headers() {
+ return {
+ Authorization: `Bearer ${apiKey}`,
+ };
+ },
+ transformer: superjson,
+ }),
+ ],
+ });
+ }
+}
+
+export async function getApiClient() {
+ if (!apiClient) {
+ await initializeClients();
+ }
+ return apiClient;
+}
+
+export async function getQueryClient() {
+ // Check if settings have changed and reinitialize if needed
+ await initializeClients();
+ return queryClient;
+}
+
+export function cleanupApiClient() {
+ apiClient = null;
+ queryClient = null;
+ currentSettings = null;
+}