Implement unified storage architecture

- Replace fragmented storage backends with single IndexedDBStorageBackend
- Create multi-store StorageBackend interface (storeName parameter)
- Remove old backends: IndexedDBBackend, LocalStorageBackend, SessionIndexedDBBackend, WebExtensionStorageBackend
- Remove old repositories: ProviderKeysRepository, SessionRepository, SettingsRepository
- Simplify AppStorage to directly expose storage methods (getSetting/setSetting, getProviderKey/setProviderKey)
- Create SessionsRepository for session-specific operations
- Update all consumers to use new simplified API
- Update example app to use new storage architecture
- Benefits: 10GB+ quota (vs 10MB chrome.storage), single database, consistent API
This commit is contained in:
Mario Zechner 2025-10-08 16:14:29 +02:00
parent b3cce7b400
commit bbbc232c7c
19 changed files with 421 additions and 998 deletions

View file

@ -1,30 +1,60 @@
import { LocalStorageBackend } from "./backends/local-storage-backend.js";
import { ProviderKeysRepository } from "./repositories/provider-keys-repository.js";
import { SessionRepository } from "./repositories/session-repository.js";
import { SettingsRepository } from "./repositories/settings-repository.js";
import type { AppStorageConfig } from "./types.js";
import { SessionsRepository } from "./sessions-repository.js";
import type { StorageBackend } from "./types.js";
/**
* High-level storage API aggregating all repositories.
* Apps configure backends and use repositories through this interface.
* High-level storage API providing access to all storage operations.
* Subclasses can extend this to add domain-specific repositories.
*/
export class AppStorage {
readonly settings: SettingsRepository;
readonly providerKeys: ProviderKeysRepository;
readonly sessions?: SessionRepository;
readonly backend: StorageBackend;
readonly sessions: SessionsRepository;
constructor(config: AppStorageConfig = {}) {
// Use LocalStorage with prefixes as defaults
const settingsBackend = config.settings ?? new LocalStorageBackend("settings");
const providerKeysBackend = config.providerKeys ?? new LocalStorageBackend("providerKeys");
constructor(backend: StorageBackend) {
this.backend = backend;
this.sessions = new SessionsRepository(backend);
}
this.settings = new SettingsRepository(settingsBackend);
this.providerKeys = new ProviderKeysRepository(providerKeysBackend);
// Settings access (delegates to "settings" store)
async getSetting<T>(key: string): Promise<T | null> {
return this.backend.get("settings", key);
}
// Session storage is optional
if (config.sessions) {
this.sessions = new SessionRepository(config.sessions);
}
async setSetting<T>(key: string, value: T): Promise<void> {
await this.backend.set("settings", key, value);
}
async deleteSetting(key: string): Promise<void> {
await this.backend.delete("settings", key);
}
async listSettings(): Promise<string[]> {
return this.backend.keys("settings");
}
// Provider keys access (delegates to "provider-keys" store)
async getProviderKey(provider: string): Promise<string | null> {
return this.backend.get("provider-keys", provider);
}
async setProviderKey(provider: string, key: string): Promise<void> {
await this.backend.set("provider-keys", provider, key);
}
async deleteProviderKey(provider: string): Promise<void> {
await this.backend.delete("provider-keys", provider);
}
async listProviderKeys(): Promise<string[]> {
return this.backend.keys("provider-keys");
}
// Quota management
async getQuotaInfo(): Promise<{ usage: number; quota: number; percent: number }> {
return this.backend.getQuotaInfo();
}
async requestPersistence(): Promise<boolean> {
return this.backend.requestPersistence();
}
}
@ -48,13 +78,3 @@ export function getAppStorage(): AppStorage {
export function setAppStorage(storage: AppStorage): void {
globalAppStorage = storage;
}
/**
* Initialize AppStorage with default configuration if not already set.
*/
export function initAppStorage(config: AppStorageConfig = {}): AppStorage {
if (!globalAppStorage) {
globalAppStorage = new AppStorage(config);
}
return globalAppStorage;
}