amico
amico copied to clipboard
[SUB-FEATURE] Implement `BrowserStorage` WASM backend
[SUB-FEATURE] Implement BrowserStorage WASM backend
📋 Summary
Provide a concrete Storage implementation that runs under wasm32-unknown-unknown, using the browser’s IndexedDB (with a LocalStorage fallback) to persist key/value blobs.
💡 Proposal
-
Module & Struct
-
Create
amico-core/src/browser_storage.rs -
Define
pub struct BrowserStorage { db_name: String, // optionally hold a handle to `web_sys::IdbDatabase` }
-
-
Initialization
-
Feature-gate on
cfg(target_arch = "wasm32") -
In constructor, open (or create) an IndexedDB database named e.g.
"amico-storage". -
Expose an async constructor:
impl BrowserStorage { pub async fn new(db_name: &str) -> Result<Self, StorageError> { … } }
-
-
Namespace & Key Mapping
- Treat each
namespaceas an object store in IndexedDB. - Use
keyas the primary key in that store. - Store values as
Uint8Arrayor base64-encoded strings for LocalStorage.
- Treat each
-
Trait Implementation
- All methods become
async fnreturningFuture<Output = Result<…, StorageError>>. -
get: open transaction, fetch key, returnNoneif missing. -
put: open readwrite transaction,putoraddthe blob. -
delete: open readwrite, calldelete. -
list_keys: open readonly, use a cursor to collect all keys.
#[async_trait::async_trait] impl Storage for BrowserStorage { async fn get(&self, namespace: &str, key: &str) -> Result<Option<Vec<u8>>, StorageError> { … } async fn put(&mut self, namespace: &str, key: &str, value: Vec<u8>) -> Result<(), StorageError> { … } async fn delete(&mut self, namespace: &str, key: &str) -> Result<(), StorageError> { … } async fn list_keys(&self, namespace: &str) -> Result<Vec<String>, StorageError> { … } } - All methods become
-
LocalStorage Fallback
- If IndexedDB isn’t available (e.g. insecure contexts), fallback to
window.localStorage. - Serialize the entire namespace map as a JSON object under a single LS key (e.g.
"amico:<namespace>").
- If IndexedDB isn’t available (e.g. insecure contexts), fallback to
-
Testing
- Write wasm-bindgen integration tests (e.g. with
wasm-pack test --headless). - Cover all operations in a browser-like environment (headless Chrome or
wasm-bindgentest runner). - Fallback LS behavior should be tested in a simulated environment where IDB isn’t present.
- Write wasm-bindgen integration tests (e.g. with
✅ Acceptance Criteria
- [ ]
browser_storage.rsmodule withBrowserStoragestruct and asyncnew()constructor. - [ ] Implements
Storagetrait (async) with correct namespace ↔ object store mapping. - [ ] IndexedDB operations using
web_sysAPIs, with appropriate error conversions toStorageError. - [ ] LocalStorage fallback path that preserves semantics.
- [ ] Integration tests exercising all four methods under both IDB and LS modes.
- [ ] Docs/comments explaining feature flag, async behavior, and fallbacks.