Skip to content

[FEATURE] Implement a storage abstraction layer #83

@takasaki404

Description

@takasaki404

[FEATURE] Implement a storage abstraction layer

📋 Summary

Provide a platform-agnostic storage interface so that Amico can persist data in environments where the OS file system is not available (e.g. WASM in the browser, in-memory caches, databases, embedded systems).

🐞 Problem

  • Currently, Amico uses the local OS file system to read/write all files.
  • In non-OS environments (WASM/browser, embedded, serverless, etc.), there is no traditional file system API.
  • We have no unified way to plug in alternative storage backends (IndexedDB, LocalStorage, in-memory, SQL/NoSQL DB, etc.).

💡 Proposed Solution

  1. Define a storage interface in the amico-core crate:

    /// Abstract key/value storage where `namespace` groups tables or
    /// directories, and each key maps to a byte array.
    pub trait Storage {
        /// Read raw bytes for `key` in `namespace`. Returns None if missing.
        fn get(&self, namespace: &str, key: &str) -> Result<Option<Vec<u8>>, StorageError>;
    
        /// Write `value` bytes for `key` in `namespace`.
        fn put(&mut self, namespace: &str, key: &str, value: Vec<u8>) -> Result<(), StorageError>;
    
        /// Delete `key` in `namespace`.
        fn delete(&mut self, namespace: &str, key: &str) -> Result<(), StorageError>;
    
        /// List all keys in `namespace`.
        fn list_keys(&self, namespace: &str) -> Result<Vec<String>, StorageError>;
    }
  2. Provide OS filesystem implementation (fs backend):

    • In dev mode: create/locate .amico/ under the project root.
    • In release mode: use a per-user data dir ($HOME/.local/share/amico/ on Linux, %APPDATA%\Amico\ on Windows, ~/Library/Application Support/Amico/ on macOS).
    • Map each namespace to a subfolder; each key to a file name (e.g. <namespace>/<key>.bin).
  3. Provide WASM/browser implementation (browser backend):

    • Feature-gated via cfg(target_arch = "wasm32").

    • Use IndexedDB (preferred) or LocalStorage fallback:

      • Map namespace to object store name; key to object key.
      • Serialize bytes to Uint8Array under the hood.
  4. Hook up selection logic

    pub enum StorageBackend {
        Fs(FsStorage),
        Browser(BrowserStorage),
        // future: InMem(InMemStorage), Db(DbStorage), etc.
    }
    
    impl Storage for StorageBackend {
        /* delegate to chosen backend */
    }
  5. Future backends (to implement later in separate PRs):

    • In-memory (for testing)
    • SQL/NoSQL database (Postgres, SQLite, DynamoDB, etc.)
    • Cloud object stores (S3, GCS)
    • Embedded flash/microcontroller FS

✅ Acceptance Criteria

  • amico-core exposes a Storage trait with get/put/delete/list_keys.

  • FsStorage works on Linux, macOS, and Windows (correct dev vs. release directory).

  • BrowserStorage compiles under wasm32-unknown-unknown and passes integration tests in browser.

  • CI matrix includes tests for both fs and browser backends.

  • Documentation added:

    • Storage trait doc comments.
    • Example usage in README or amico-cli demo.
  • (Optional) Add a simple in-memory backend for unit testing.

Sub-issues

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions