UNPKG

@silver-zepp/easy-storage

Version:

The Easy Storage library offers a suite of storage solutions designed for ZeppOS applications, providing a range of data persistence strategies to accommodate different data management needs.

284 lines (242 loc) 13.4 kB
# 📦 Easy Storage Library for ZeppOS ## EasyStorage 2.0 Update: `AsyncStorage` & `EasyStorageAsync` added! - This update brings Async storage solutions that don't render block the UI and barely consume any CPU power making UI/UX interaction buttery smooth. - If you've been with us for a while, you know that our `ZeppOS` storage solution is **slow**, and whenever you read or write a file, the whole UI freezes; moreover the bigger the file, the worse it feels. - With `AsyncStorage` and `EasyStorageAsync` solutions this is no longer the case. Take a look at the example youtube video below. <a href="https://youtu.be/DEkwlz1RCa4"> <img src="https://img.youtube.com/vi/DEkwlz1RCa4/maxresdefault.jpg" width="640" height="360"> </a> > [!NOTE] > This solution should be useful for mini apps that have menus with dynamic updates (quick ON/OFF switch), games and apps that have to write / read data during runtime, as well as advanced watch face developers that rely on storage operations. ## How to use new `AsyncStorage` & `EasyStorageAsync` (bare minimum code samples) > [!TIP] > you can download working example shown above from the [example-apps/showcase](https://github.com/silver-zepp/zeppos-easy-storage/tree/master/example-apps/easy-storage-showcase/) folder ### Install `EasyStorage` ```js npm i @silver-zepp/easy-storage ``` ### 1. `AsyncStorage` - Queued JSON file operations that won't overwhelm CPU and freeze UI during big writes/reads - Automatically streams large datasets in small chunks to stay responsive - Built-in flow control prevents overwhelming the system with too many operations - Graceful shutdown saves any pending writes before app exits. Add `AsyncStorage.SaveAndQuit();` to your page's onDestroy(). > [!TIP] > `AsyncStorage` example page [async-storage.js](https://github.com/silver-zepp/zeppos-easy-storage/tree/master/example-apps/easy-storage-showcase/test-pages/async-storage.js) ```js import { AsyncStorage } from "@silver-zepp/easy-storage"; // write AsyncStorage.WriteJson('config.json', { theme: 'dark' }, (err, ok) => { if (ok) console.log('config saved!'); }); // read AsyncStorage.ReadJson('config.json', (err, config) => { if (!err) { console.log('theme:', config.theme); // apply your theme to UI widget // ... } }); // === ADDITIONAL HELPERS === // // example: throttle file operations to prevent overload and RAM runout if (!AsyncStorage.IsBusy()) { AsyncStorage.WriteJson('data.json', big_obj, callback); } else { console.log('storage busy, try again later'); } // immediately save all pending writes synchronously (if any) // making sure no data is lost on app crash or a force-close during write times Page({ // ... onDestroy() { AsyncStorage.SaveAndQuit(); }, }) ``` ### 2. `EasyStorageAsync` - Single-file JSON blob kept in RAM, synced to disk without blocking UI - Perfect for larger settings/prefs that might cause stutter with sync writes - Queued autosave prevents overwhelming the storage system - Same API as EasyStorage but all operations use callbacks > [!TIP] > `EasyStorageAsync` example page [easy-storage-async.js](https://github.com/silver-zepp/zeppos-easy-storage/tree/master/example-apps/easy-storage-showcase/test-pages/easy-storage-async.js) For the most part API remains the same as `EasyStorage` (sync) and works as a drop in replacement, reusing its old storage database file `easy_storage.js` but there are a few areas you have to pay attention to observing the example. ```js // basic interaction remains the same import { EasyStorageAsync } from "@silver-zepp/easy-storage"; const storage = new EasyStorageAsync(); Page({ onInit() { // =============================== // Manual Storage Synchronization: // =============================== // by default EasyStorageAsync loads its database file in a lazy-load async manner to avoid UI lag // without manual syncronization, your keys might not be available at access time // this is (optional) and should be used only when data concistency is necessary right away. // the sync, if necessary, has to be done only once. after that, the whole DB remains in RAM if (!storage.isReady()) storage.synchronize(); }, build() { storage.setKey("name", "John"); // set the key const name = storage.getKey("name"); // get the key }, onDestroy() { // immediately save all pending writes synchronously (if any) // making sure no data is lost on app crash or a force-close during write times storage.saveAndQuit(); } }) // === ADDITIONAL ASYNC BENEFITS === // // now that the writes are asynchronous you can rely on write callback when the value finished storing storage.setKey('theme', 'dark', (err, ok) => { if (ok) console.log('saved without blocking UI'); }); ``` ### The rest of the API remains mostly the same and you can read about it below ### 3. `EasyStorage` [[Read API🔗]](./docs/easy-storage.md) - Single-file JSON blob kept in RAM, synced to disk on every change - Perfect for small settings or user prefs reads/writes - Autosave guarantees data survives app restarts - Simple but rewrites entire file; not ideal for very large datasets ```js import { EasyStorage } from "@silver-zepp/easy-storage"; const storage = new EasyStorage(); storage.setKey("name", "John Doe"); console.log(storage.getKey("user")); // "John Doe" ``` ### 4. `EasyTSDB` [[Read API🔗]](./docs/easy-tsdb.md) - Lightweight time-series database; buffers points in RAM, shards to JSON files - Auto-flush on size or timer keeps RAM low without losing data - Built-in sum/avg/min/max plus pluggable custom aggregations - Indexed file layout accelerates range queries - ideal for sensor logs ```js import { EasyTSDB } from "@silver-zepp/easy-storage"; const db = new EasyTSDB(); // write some data points db.writePoint('temperature', 22.5); // if not provided -> use the current timestamp db.writePoint('humidity', 55, Date.now() - 60 * 60 * 1000); // 1 hour ago // query the average temperature over the last 2 hours const start_time = Date.now() - 2 * 60 * 60 * 1000; // 2 hours ago const end_time = Date.now(); const avg_temp = db.query(start_time, end_time, 'average'); console.log(`Average temperature over the last 2 hours: ${avg_temp}`); ``` ### 5. `EasyFlashStorage` [[Read API🔗]](./docs/easy-flash-storage.md) - Handles data sets that are too large for EasyStorage's single-blob model - Minimizes RAM usage – only the file you're working with is loaded - Reduces flash wear: small writes instead of rewriting a big file - Survives unexpected reboots; corruption is isolated to one key ```js import { EasyFlashStorage } from "@silver-zepp/easy-storage"; const flash = new EasyFlashStorage(); flash.setKey("config", { theme: "dark", notifications: true, ... }); console.log(flash.getKey("config")); ``` ### 6. `EasyTempStorage` [[Read API🔗]](./docs/easy-temp-storage.md) - Pure in-memory key-value cache, zero disk I/O - Fastest choice for data that matters only while the app is open - Cleared automatically on exit; no cleanup needed - Shares EasyStorage-style API for easy swapping ```js import { EasyTempStorage } from "@silver-zepp/easy-storage"; const temp = new EasyTempStorage(); temp.setKey("session", { token: "abc123" }); console.log(temp.getKey("session")); ``` ### 7. `Storage` [[Read API🔗]](./docs/storage.md) - Direct file operations that happen immediately and block until complete - Perfect for small files and simple read/write tasks where you need the result right away - No queuing or async complexity - just straightforward "save this now" functionality - Use `AsyncStorage` instead if you're dealing with large files or don't want UI stuttering ```js import { Storage } from "@silver-zepp/easy-storage"; Storage.WriteFile("log.txt", "log entry example"); console.log(Storage.ReadFile("log.txt")); ``` # 📐 Library Quick API ### EasyStorageAsync - `setKey(key, value, callback?)`: Stores a value; queued to disk without blocking UI. - `getKey(key, defaultValue?)`: Returns a value immediately from RAM (or default). - `hasKey(key)`: Returns `true` if the key exists in RAM. - `removeKey(key, callback?)`: Deletes a key; write is queued. - `saveAll(callback?)`: Flushes all in-RAM data to disk now. - `deleteAll(callback?)`: Clears every key and saves an empty blob. - `printContents()`: Logs the current in-RAM store to console. - `getStorageSnapshot(stringify?)`: Returns the whole store as object or JSON string. - `saveAndQuit()`: Forces final flush; returns `{ saved }` count. - `isBusy()`: `true` when the internal queue is saturated. - `SetAutosaveEnable(bool)`: Toggles periodic autosave timer. - `SetStorageFilename(filename)`: Changes the on-disk filename for future saves. - `GetStorageFilename()`: Returns the current filename in use. - `isReady()`: `true` once the initial async load has finished. - `synchronize()`: Synchronous fallback; loads file into RAM instantly. ### AsyncStorage - `WriteJson(filename, json, callback?)`: Queues a JSON write; non-blocking. - `ReadJson(filename, callback?)`: Queues a JSON read and parses result. - `RemoveFile(filename, callback?)`: Deletes a file (quick sync op). - `IsBusy()`: Returns `true` if the operation queue is near capacity. - `SaveAndQuit()`: Flushes all pending writes and returns `{ saved }` count. ### EasyStorage - `setKey(key, value)`: Stores or updates a value for a key. - `getKey(key, defaultValue)`: Retrieves the value of a key. - `hasKey(key)`: Checks existence of a key. - `removeKey(key)`: Deletes a key and its associated value. - `saveAll()`: Forces saving all key-value pairs to the file. - `deleteAll()`: Deletes all keys and values. - `printContents()`: Displays all storage contents. - `getStorageSnapshot(stringify)`: Returns storage contents as a string or object. - `SetAutosaveEnable(bool)`: Enables or disables autosave. - `SetStorageFilename(filename)`: Changes the storage file name. - `GetStorageFilename()`: Returns the current storage filename. ### EasyTSDB (time-series database) - `writePoint(measurement, value, timestamp)`: Writes a data point. - `query(start_time, end_time, aggregation_type, custom_aggregator)`: Queries data with aggregation. - `retrieveDataSeries(start_time, end_time)`: Retrieves raw data points. - `purge(older_than)`: Removes data points older than a specified timestamp. - `databaseClear(consent)`: Clears all database data. - `databaseClose()`: Closes the database, flushing data to disk. - `databaseBackup(backup_path, include_index)`: Backups the database. - `databaseRestore(consent, backup_path, recalculate_index)`: Restores the database from a backup. ### EasyFlashStorage - `setKey(key, value)`: Stores or updates a value for a key, saving it to a file. - `getKey(key)`: Retrieves the value of a key from a file. - `removeKey(key)`: Deletes a file associated with a key. - `hasKey(key)`: Checks for the existence of a file for a key. - `dataSize(key, unit)`: Calculates the size of a file for a key. - `size(unit)`: Calculates the total size of all storage files. - `getAllKeys(stringify)`: Lists all keys in storage. - `getAllValues(stringify)`: Lists all values in storage. - `getStorageSnapshot(stringify)`: Returns all storage contents as a string or object. - `deleteAll()`: Deletes all keys and values, removing associated files. - `printAllKeys()`: Displays all keys and their values. ### EasyTempStorage - `setKey(key, value)`: Temporarily stores a value for a key. - `getKey(key, defaultValue)`: Retrieves a value of a key. - `hasKey(key)`: Checks existence of a key. - `removeKey(key)`: Deletes a key and its value. - `deleteAll()`: Clears all keys and values. - `printAllKeys()`: Displays all keys and values. - `getAllKeys(stringify)`: Lists all keys in temporary storage. ### Storage - `WriteJson(filename,json)` : Writes a JSON object to a file. - `ReadJson(filename)`: Reads a JSON object from a file. - `WriteFile(filename, data)`: Writes data to a file. - `ReadFile(filename)`: Reads data from a file. - `RemoveFile(filename)`: Deletes a file. - `WriteAsset(filename, data)`: Writes data to an asset file. - `ReadAsset(filename)`: Reads data from an asset file. - `MakeDirectory(dirname)`: Creates a new directory. - `ListDirectory(dirname)`: Lists contents of a directory. - `FileInfo(path)`: Returns size, mtime and other stats for a file or dir. - `Exists(path)`: Checks whether a file or directory exists. - `CopyFile(src, dest)`: Copies a file to a new location. - `MoveFile(src, dest)`: Moves (renames) a file; implemented as copy + delete. - `IsFile(path)`: Returns `true` if the path points to a regular file. - `IsDir(path)`: Returns `true` if the path points to a directory. - `FileSize(path)`: Returns the size of a file in bytes (0 if missing). - `FileChangeTime(path)`: Returns the last-modified timestamp in ms. # 📝 EasyStorage API Reference ### 1. [EasyStorage API🔗](./docs/easy-storage.md) ### 2. [EasyTSDB API🔗](./docs/easy-tsdb.md) ### 3. [EasyFlashStorage API🔗](./docs/easy-flash-storage.md) ### 4. [EasyTempStorage API🔗](./docs/easy-temp-storage.md) ### 5. [Storage API🔗](./docs/storage.md)