[FEATURE] Implement a `storage` abstraction layer
[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
-
Define a storage interface in the
amico-corecrate:/// 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>; } -
Provide OS filesystem implementation (
fsbackend):- 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
namespaceto a subfolder; eachkeyto a file name (e.g.<namespace>/<key>.bin).
- In dev mode: create/locate
-
Provide WASM/browser implementation (
browserbackend):-
Feature-gated via
cfg(target_arch = "wasm32"). -
Use IndexedDB (preferred) or LocalStorage fallback:
- Map
namespaceto object store name;keyto object key. - Serialize bytes to
Uint8Arrayunder the hood.
- Map
-
-
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 */ } -
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-coreexposes aStoragetrait withget/put/delete/list_keys. -
[ ]
FsStorageworks on Linux, macOS, and Windows (correct dev vs. release directory). -
[ ]
BrowserStoragecompiles underwasm32-unknown-unknownand passes integration tests in browser. -
[ ] CI matrix includes tests for both
fsandbrowserbackends. -
[ ] Documentation added:
-
Storagetrait doc comments. - Example usage in README or
amico-clidemo.
-
-
[ ] (Optional) Add a simple in-memory backend for unit testing.