Generated by Spark: Reduce reliance on spark database. Just use sqlite.

This commit is contained in:
2026-01-17 18:14:23 +00:00
committed by GitHub
parent 0f01311120
commit 270d0be790
8 changed files with 1387 additions and 0 deletions

101
src/hooks/use-indexed-db.ts Normal file
View File

@@ -0,0 +1,101 @@
import { useState, useEffect, useCallback } from 'react'
import { db, type DBSchema } from '@/lib/db'
type StoreName = keyof DBSchema
export function useIndexedDB<T extends StoreName, V = DBSchema[T]['value']>(
storeName: T,
key?: string,
defaultValue?: V
): [V | undefined, (value: V) => Promise<void>, () => Promise<void>, boolean] {
const [value, setValue] = useState<V | undefined>(defaultValue)
const [loading, setLoading] = useState(true)
useEffect(() => {
if (!key) {
setLoading(false)
return
}
let mounted = true
db.get(storeName, key)
.then((result) => {
if (mounted) {
setValue((result as V) || defaultValue)
setLoading(false)
}
})
.catch((error) => {
console.error(`Error loading ${storeName}/${key}:`, error)
if (mounted) {
setValue(defaultValue)
setLoading(false)
}
})
return () => {
mounted = false
}
}, [storeName, key, defaultValue])
const updateValue = useCallback(
async (newValue: V) => {
if (!key) {
throw new Error('Cannot update value without a key')
}
setValue(newValue)
try {
await db.put(storeName, newValue as any)
} catch (error) {
console.error(`Error saving ${storeName}/${key}:`, error)
throw error
}
},
[storeName, key]
)
const deleteValue = useCallback(async () => {
if (!key) {
throw new Error('Cannot delete value without a key')
}
setValue(undefined)
try {
await db.delete(storeName, key)
} catch (error) {
console.error(`Error deleting ${storeName}/${key}:`, error)
throw error
}
}, [storeName, key])
return [value, updateValue, deleteValue, loading]
}
export function useIndexedDBCollection<T extends StoreName>(
storeName: T
): [DBSchema[T]['value'][], () => Promise<void>, boolean] {
const [items, setItems] = useState<DBSchema[T]['value'][]>([])
const [loading, setLoading] = useState(true)
const refresh = useCallback(async () => {
setLoading(true)
try {
const result = await db.getAll(storeName)
setItems(result)
} catch (error) {
console.error(`Error loading ${storeName} collection:`, error)
} finally {
setLoading(false)
}
}, [storeName])
useEffect(() => {
refresh()
}, [refresh])
return [items, refresh, loading]
}

67
src/hooks/use-storage.ts Normal file
View File

@@ -0,0 +1,67 @@
import { useState, useEffect, useCallback } from 'react'
import { storage } from '@/lib/storage'
export function useStorage<T>(
key: string,
defaultValue: T
): [T, (value: T | ((prev: T) => T)) => Promise<void>, () => Promise<void>] {
const [value, setValue] = useState<T>(defaultValue)
const [isInitialized, setIsInitialized] = useState(false)
useEffect(() => {
let mounted = true
storage
.get<T>(key)
.then((storedValue) => {
if (mounted) {
if (storedValue !== undefined) {
setValue(storedValue)
}
setIsInitialized(true)
}
})
.catch((error) => {
console.error(`Error loading ${key}:`, error)
if (mounted) {
setIsInitialized(true)
}
})
return () => {
mounted = false
}
}, [key])
const updateValue = useCallback(
async (newValueOrUpdater: T | ((prev: T) => T)) => {
const newValue =
typeof newValueOrUpdater === 'function'
? (newValueOrUpdater as (prev: T) => T)(value)
: newValueOrUpdater
setValue(newValue)
try {
await storage.set(key, newValue)
} catch (error) {
console.error(`Error saving ${key}:`, error)
throw error
}
},
[key, value]
)
const deleteValue = useCallback(async () => {
setValue(defaultValue)
try {
await storage.delete(key)
} catch (error) {
console.error(`Error deleting ${key}:`, error)
throw error
}
}, [key, defaultValue])
return [isInitialized ? value : defaultValue, updateValue, deleteValue]
}