aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAryan Keluskar <[email protected]>2025-11-06 22:20:57 -0800
committerGitHub <[email protected]>2025-11-06 22:20:57 -0800
commit7e692f9862d31cf455ea6a9ba545df2f52cf74f1 (patch)
tree64da73867524e4a707ae7b6eadd76b815350d864
parentredeploy (diff)
downloadsupermemory-7e692f9862d31cf455ea6a9ba545df2f52cf74f1.tar.xz
supermemory-7e692f9862d31cf455ea6a9ba545df2f52cf74f1.zip
Migrate Chat Persistence from localStorage to IndexedDB to Fix QuotaExceededError (#560)
-rw-r--r--apps/web/package.json1
-rw-r--r--apps/web/stores/chat.ts4
-rw-r--r--apps/web/stores/indexeddb-storage.ts24
-rw-r--r--bun.lock3
4 files changed, 31 insertions, 1 deletions
diff --git a/apps/web/package.json b/apps/web/package.json
index e2247046..46bfa8fb 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -59,6 +59,7 @@
"embla-carousel-autoplay": "^8.6.0",
"embla-carousel-react": "^8.6.0",
"framer-motion": "^12.23.12",
+ "idb-keyval": "^6.2.2",
"is-hotkey": "^0.2.0",
"lucide-react": "^0.525.0",
"masonic": "^4.1.0",
diff --git a/apps/web/stores/chat.ts b/apps/web/stores/chat.ts
index ac204442..f1701139 100644
--- a/apps/web/stores/chat.ts
+++ b/apps/web/stores/chat.ts
@@ -1,7 +1,8 @@
import type { UIMessage } from "@ai-sdk/react"
import { create } from "zustand"
-import { persist } from "zustand/middleware"
+import { persist, createJSONStorage } from "zustand/middleware"
import { useCallback } from "react"
+import { indexedDBStorage } from "./indexeddb-storage"
/**
* Deep equality check for UIMessage arrays to prevent unnecessary state updates
@@ -175,6 +176,7 @@ export const usePersistentChatStore = create<ConversationsStoreState>()(
}),
{
name: "supermemory-chats",
+ storage: createJSONStorage(() => indexedDBStorage),
},
),
)
diff --git a/apps/web/stores/indexeddb-storage.ts b/apps/web/stores/indexeddb-storage.ts
new file mode 100644
index 00000000..c2a1db91
--- /dev/null
+++ b/apps/web/stores/indexeddb-storage.ts
@@ -0,0 +1,24 @@
+import { get, set, del } from 'idb-keyval';
+
+export const indexedDBStorage = {
+ getItem: async (name: string) => {
+ let value = await get(name);
+ if (value !== undefined) {
+ return value;
+ }
+ // Migrate from localStorage if exists
+ value = localStorage.getItem(name);
+ if (value !== null) {
+ await set(name, value);
+ localStorage.removeItem(name);
+ return value;
+ }
+ return null;
+ },
+ setItem: async (name: string, value: string) => {
+ await set(name, value);
+ },
+ removeItem: async (name: string) => {
+ await del(name);
+ },
+};
diff --git a/bun.lock b/bun.lock
index cad35279..2c82cc12 100644
--- a/bun.lock
+++ b/bun.lock
@@ -140,6 +140,7 @@
"embla-carousel-autoplay": "^8.6.0",
"embla-carousel-react": "^8.6.0",
"framer-motion": "^12.23.12",
+ "idb-keyval": "^6.2.2",
"is-hotkey": "^0.2.0",
"lucide-react": "^0.525.0",
"masonic": "^4.1.0",
@@ -2884,6 +2885,8 @@
"iconv-lite": ["[email protected]", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
+ "idb-keyval": ["[email protected]", "", {}, "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg=="],
+
"ieee754": ["[email protected]", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
"ignore": ["[email protected]", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],