amico icon indicating copy to clipboard operation
amico copied to clipboard

[SUB-FEATURE] Implement `BrowserStorage` WASM backend

Open takasaki404 opened this issue 8 months ago • 0 comments

[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

  1. Module & Struct

    • Create amico-core/src/browser_storage.rs

    • Define

      pub struct BrowserStorage {
          db_name: String,
          // optionally hold a handle to `web_sys::IdbDatabase`
      }
      
  2. 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> { … }
      }
      
  3. Namespace & Key Mapping

    • Treat each namespace as an object store in IndexedDB.
    • Use key as the primary key in that store.
    • Store values as Uint8Array or base64-encoded strings for LocalStorage.
  4. Trait Implementation

    • All methods become async fn returning Future<Output = Result<…, StorageError>>.
    • get: open transaction, fetch key, return None if missing.
    • put: open readwrite transaction, put or add the blob.
    • delete: open readwrite, call delete.
    • 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> { … }
    }
    
  5. 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>").
  6. 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-bindgen test runner).
    • Fallback LS behavior should be tested in a simulated environment where IDB isn’t present.

✅ Acceptance Criteria

  • [ ] browser_storage.rs module with BrowserStorage struct and async new() constructor.
  • [ ] Implements Storage trait (async) with correct namespace ↔ object store mapping.
  • [ ] IndexedDB operations using web_sys APIs, with appropriate error conversions to StorageError.
  • [ ] 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.

takasaki404 avatar May 08 '25 04:05 takasaki404