# Documentation
## **File: `externalStorage.go`**
### **Package: `storage`**
This package provides an interface and implementation for handling external storage in a WebAssembly (WASM) environment, enabling key-value persistence across external storage solutions.
#### **Interface: `ExternalStorage`**
Defines methods for managing persistent state in key-value format.
- **`Get(key string) ([]byte, error)`**
Retrieves and decodes a value from external storage using the given key. Returns `os.ErrNotExist` if the key does not exist.
- **`Set(key string, value []byte) error`**
Encodes a byte array into a string and stores it in external storage under the given key. Returns an error if storage quota is exceeded.
- **`Delete(keyName string) error`**
Removes the value associated with the given key from external storage. Does nothing if the key does not exist.
- **`Clear() (int, error)`**
Deletes all keys stored by this WASM binary. Returns the number of keys cleared.
- **`ClearPrefix(prefix string) (int, error)`**
Deletes all keys that start with the given prefix. Returns the number of keys cleared.
- **`Key(n int) (string, error)`**
Retrieves the name of the nth key stored. Returns `os.ErrNotExist` if no such key exists.
- **`Keys() ([]string, error)`**
Returns a list of all key names stored in external storage.
- **`ExternalStorageUNSAFE() *HavenStorageJS`**
Returns a low-level access wrapper for the external storage. This is **unsafe** and should be used cautiously.
---
### **Implementation: `externalStorage`**
Provides a concrete implementation of the `ExternalStorage` interface.
- **`newExternalStorage(prefix string) *externalStorage`**
Initializes an `externalStorage` instance with a given prefix.
- **`GetExternalStorage() ExternalStorage`**
Returns a global instance of `externalStorage`.
- **`(ls *externalStorage) Get(keyName string) ([]byte, error)`**
Fetches a value from external storage, decoding it using Base32768 encoding.
- **`(ls *externalStorage) Set(keyName string, keyValue []byte) error`**
Encodes data in Base32768 and stores it in external storage.
- **`(ls *externalStorage) Delete(keyName string) error`**
Removes a key from external storage.
- **`(ls *externalStorage) Clear() (int, error)`**
Clears all keys in storage.
- **`(ls *externalStorage) ClearPrefix(prefix string) (int, error)`**
Clears all keys with a specific prefix.
- **`(ls *externalStorage) Key(n int) (string, error)`**
Retrieves the nth key stored.
- **`(ls *externalStorage) Keys() ([]string, error)`**
Retrieves a list of all keys.
- **`(ls *externalStorage) ExternalStorageUNSAFE() *HavenStorageJS`**
Returns direct access to the external storage JavaScript wrapper.
---
### **JavaScript Wrapper: `HavenStorageJS`**
Encapsulates JavaScript’s `window.havenStorage` object.
- **`(ls *HavenStorageJS) GetItem(keyName string) (string, error)`**
Fetches an item from external storage.
- **`(ls *HavenStorageJS) SetItem(keyName, keyValue string) error`**
Stores an item in external storage.
- **`(ls *HavenStorageJS) Delete(keyName string) error`**
Removes an item from external storage.
- **`(ls *HavenStorageJS) Clear() error`**
Clears all stored keys.
- **`(ls *HavenStorageJS) Key(n int) (string, error)`**
Retrieves the nth key.
- **`(ls *HavenStorageJS) Keys() ([]string, error)`**
Fetches a list of all keys.
- **`(ls *HavenStorageJS) KeysPrefix(prefix string) ([]string, error)`**
Fetches all keys that match a specific prefix.
---
#### **Helper Functions**
- **`checkUnimplementedErr(jsErr []js.Value) error`**
Checks if an error is an "Unimplemented" error and returns a standardized error.
- **`callStorage(op StorageOperation, args ...interface{}) js.Value`**
Calls JavaScript’s storage API with the given operation and arguments.
## **Test File: `externalStorage_test.go`**
This file contains unit tests for the `storage` package, verifying the correctness of the `ExternalStorage` interface and its implementation.
---
### **Setup Function**
#### **`setupMockHavenStorage(t *testing.T)`**
- Initializes a mock version of `havenStorage` in the JavaScript environment using `localStorage`.
- Defines the following JavaScript functions:
- `getItem(key)`: Retrieves an item from `localStorage`.
- `setItem(key, value)`: Stores an item in `localStorage`.
- `delete(key)`: Removes an item from `localStorage`.
- `clear()`: Clears `localStorage`.
- `getKeys()`: Retrieves all stored keys.
- `key(index)`: Always rejects with a "not implemented" error.
- Calls `newExternalStorage` to initialize the global storage instance.
---
### **Unit Tests**
#### **`TestGetExternalStorage(t *testing.T)`**
- Ensures that `GetExternalStorage()` correctly returns an instance of `externalStorage`.
#### **`TestExternalStorage_Get_Set(t *testing.T)`**
- Tests setting and retrieving values from storage.
- Stores different data types (`string`, `byte slices`).
- Verifies that retrieved values match the original input.
#### **`TestExternalStorage_Delete(t *testing.T)`**
- Tests that deleting a key removes it from storage.
- Verifies that attempting to retrieve the deleted key returns `os.ErrNotExist`.
#### **`TestExternalStorage_Clear(t *testing.T)`**
- Ensures that `Clear()` removes all keys stored by the WASM binary.
- Differentiates between prefixed and non-prefixed keys.
- Verifies that only the prefixed keys are deleted.
#### **`TestExternalStorage_ClearPrefix(t *testing.T)`**
- Ensures that `ClearPrefix(prefix)` removes only keys with the specified prefix.
- Confirms that non-matching keys remain in storage.
#### **`TestExternalStorage_Key(t *testing.T)`**
- Tests that calling `Key(n)` returns `UnimplementedErr`, as the mock implementation does not support this operation.
#### **`TestExternalStorage_Get_NotExistError(t *testing.T)`**
- Ensures that attempting to retrieve a non-existent key returns `os.ErrNotExist`.
#### **`TestExternalStorage_Keys(t *testing.T)`**
- Verifies that `Keys()` returns all stored key names.
- Checks that the number of retrieved keys matches expectations.
- Ensures that all expected keys exist in the returned list.
---