Storage Service
8.12 StorageService — Scoped key-value persistence
Runs in: both worker and view. Writes from the worker are the source of truth for state that needs to survive view eviction.
Permission required: storage:read for reads, storage:write for writes.
The recommended way to persist extension data across sessions. Each extension gets its own isolated namespace backed by SQLite on the Rust side — extensions cannot read or write other extensions' data.
interface IStorageService {
get(key: string): Promise<string | null>;
set(key: string, value: string): Promise<void>;
delete(key: string): Promise<boolean>;
getAll(): Promise<Record<string, string>>;
clear(): Promise<number>;
}
Usage:
const storage = context.getService<IStorageService>('storage');
// Store a value (values are strings — JSON.stringify complex data)
await storage.set('theme', 'dark');
await storage.set('bookmarks', JSON.stringify(['https://example.com']));
// Read a value
const theme = await storage.get('theme'); // "dark"
const raw = await storage.get('bookmarks');
const bookmarks = raw ? JSON.parse(raw) : [];
// Check if a key exists
const val = await storage.get('nonexistent'); // null
// Delete a single key
const wasDeleted = await storage.delete('theme'); // true
// Get everything
const all = await storage.getAll(); // { "bookmarks": "[\"https://example.com\"]" }
// Nuclear option — delete all your extension's data
const count = await storage.clear(); // number of deleted entries
How it works under the hood:
All extensions share one extension_storage table in asyar_data.db (SQLite, WAL mode). The IPC Router automatically injects your extensionId into every call — you never see it, and you cannot impersonate another extension. On uninstall, Asyar deletes all rows for your extension automatically.
When to use what:
| Need | Use |
|---|---|
| Persist data across sessions (user preferences, notes, stable state) | StorageService |
| Transient data with an expiration (API responses, search indexes) | CacheService |
| Transient state within a single session | localStorage (iframe-scoped, survives view navigation) |
| App-wide settings with reactive change subscriptions | SettingsService |
Pro Tip: Values are plain strings. For objects and arrays, use
JSON.stringify/JSON.parse. Keep keys short and descriptive — there's no size limit, but the entire table is shared across all extensions.