story-research-zapwall/lib/settingsCache.ts
2026-01-06 14:17:55 +01:00

131 lines
3.6 KiB
TypeScript

/**
* IndexedDB cache for application settings (excluding keys)
* Stores settings and last sync date for background synchronization
*/
const DB_NAME = 'nostr_paywall_settings'
const DB_VERSION = 1
const STORE_NAME = 'settings'
export interface SettingsData {
// Settings excluding keys (relays, NIP-95 APIs, etc.)
relays?: Array<{ id: string; url: string; enabled: boolean; priority: number; createdAt: number }>
nip95Apis?: Array<{ id: string; url: string; enabled: boolean; priority: number; createdAt: number }>
platformLightningAddress?: string
// Last sync date (Unix timestamp) for background synchronization
lastSyncDate?: number
// Metadata
updatedAt: number
}
class SettingsCacheService {
private db: IDBDatabase | null = null
private async initDB(): Promise<IDBDatabase> {
if (this.db) {
return this.db
}
return new Promise((resolve, reject) => {
if (typeof window === 'undefined' || !window.indexedDB) {
reject(new Error('IndexedDB is not available'))
return
}
const request = indexedDB.open(DB_NAME, DB_VERSION)
request.onerror = () => {
reject(new Error(`Failed to open IndexedDB: ${request.error}`))
}
request.onsuccess = () => {
this.db = request.result
resolve(this.db)
}
request.onupgradeneeded = (event) => {
const db = (event.target as IDBOpenDBRequest).result
if (!db.objectStoreNames.contains(STORE_NAME)) {
const store = db.createObjectStore(STORE_NAME, { keyPath: 'key' })
store.createIndex('updatedAt', 'updatedAt', { unique: false })
}
}
})
}
/**
* Get settings (excluding keys) and last sync date
*/
async getSettings(): Promise<SettingsData | null> {
try {
const db = await this.initDB()
const transaction = db.transaction([STORE_NAME], 'readonly')
const store = transaction.objectStore(STORE_NAME)
return new Promise((resolve, reject) => {
const request = store.get('settings')
request.onsuccess = () => {
const result = request.result as { key: string; value: SettingsData } | undefined
resolve(result?.value ?? null)
}
request.onerror = () => reject(request.error)
})
} catch (error) {
console.error('Error retrieving settings from cache:', error)
return null
}
}
/**
* Save settings (excluding keys) and last sync date
*/
async saveSettings(settings: SettingsData): Promise<void> {
try {
const db = await this.initDB()
const transaction = db.transaction([STORE_NAME], 'readwrite')
const store = transaction.objectStore(STORE_NAME)
await new Promise<void>((resolve, reject) => {
const request = store.put({
key: 'settings',
value: {
...settings,
updatedAt: Date.now(),
},
})
request.onsuccess = () => resolve()
request.onerror = () => reject(request.error)
})
} catch (error) {
console.error('Error saving settings to cache:', error)
throw error
}
}
/**
* Update last sync date
*/
async updateLastSyncDate(timestamp: number): Promise<void> {
const settings = await this.getSettings()
await this.saveSettings({
...settings,
lastSyncDate: timestamp,
updatedAt: Date.now(),
} as SettingsData)
}
/**
* Get last sync date
*/
async getLastSyncDate(): Promise<number | null> {
const settings = await this.getSettings()
return settings?.lastSyncDate ?? null
}
}
export const settingsCache = new SettingsCacheService()