elf-hyperbee-persist v1.0.2
elf-hyperbee-persist
elf-hyperbee-persist is a library for managing state persistence and synchronization between a Hyperbee instance and an RxJS Elf store. These utilities ensure that state changes are efficiently loaded and persisted using reactive programming principles.
Features
- State Persistence: Automatically save changes from an Elf store into Hyperbee.
- State Loading: Retrieve existing state entries from Hyperbee into the Elf store.
- Support for Prefixed and Non-Prefixed Keys: Works with both structured
[prefix, key]formats and direct keys. - Efficient Updates: Uses RxJS to minimize redundant writes and optimize performance.
- Deep Equality Checks: Ensures that only actual state changes are persisted.
- Composable RxJS Pipelines: Designed to be easily integrated with other reactive workflows.
Installation
Install the package via npm:
npm install elf-hyperbee-persistCompatibility
elf-hyperbee-persist is designed to work in both Node.js and Bare environments.
Node.js Compatibility:
- Fully supports ES modules (
import). - Works with Hyperbee, RxJS, and Elf for efficient state management.
- Fully supports ES modules (
Bare Environment Compatibility:
- Can run in environments without traditional Node.js dependencies.
- Uses
bare:testto ensure functionality in Bare-based runtimes.
Running Tests for Both Environments
To ensure compatibility, both standard and Bare tests are included:
# Standard Node.js test
npm test
# Test in Bare runtime
npm run bare:testAPI
loadStateFromHyperbee$
import { loadStateFromHyperbee$ } from "elf-hyperbee-persist";Loads persisted state from Hyperbee into an RxJS Elf store.
Parameters:
hyperbee: The Hyperbee instance to read the state from.elfStore: The store where the loaded state will be applied.options.prefix(default:"state"): If provided, filters keys that start with this prefix.- If
prefixisnull, keys are assumed to be stored as direct keys instead of[prefix, key].
- If
Returns:
An RxJS observable that, when subscribed to, loads the state into the Elf store.
Example Usage:
// Using prefixed keys
loadStateFromHyperbee$(hyperbeeInstance, myElfStore, { prefix: "gameState" }).subscribe();
// Using non-prefixed keys
loadStateFromHyperbee$(hyperbeeInstance, myElfStore, { prefix: null }).subscribe();persistStateIntoHyperbee$
import { persistStateIntoHyperbee$ } from "elf-hyperbee-persist";Watches for state changes in the Elf store and persists them into Hyperbee.
Parameters:
hyperbee: The Hyperbee instance to persist the state into.elfStore: The RxJS Elf store tracking state changes.options.prefix(default:"state"): If provided, persists state using[prefix, key]format.- If
prefixisnull, stores keys directly without structuring them as arrays.
- If
options.debounce(default:1000): Debounce time in milliseconds before persisting updates.options.cas(default: a deep equality check): A compare-and-swap (CAS) function that determines whether an entry should be updated in Hyperbee.- Accepts two parameters:
prev(previous entry) andcurr(new entry). - Should return
trueif the entry should be updated.
- Accepts two parameters:
options.distinct(default: a deep equality check): A function that determines whether state updates are considered distinct.- Used in
distinctUntilChangedto filter redundant updates. - Accepts two consecutive state values and should return
trueif they are the same (i.e., no need to update).
- Used in
Returns:
An RxJS observable that processes state updates and saves them to Hyperbee.
Example Usage:
// Using prefixed keys
persistStateIntoHyperbee$(hyperbeeInstance, myElfStore, { prefix: "gameState" }).subscribe();
// Using non-prefixed keys
persistStateIntoHyperbee$(hyperbeeInstance, myElfStore, { prefix: null }).subscribe();
// Using a custom CAS function
const customCas = (prev, curr) => prev.version !== curr.version;
persistStateIntoHyperbee$(hyperbeeInstance, myElfStore, { cas: customCas }).subscribe();
// Using a custom distinct function
const customDistinct = ([prev, curr]) => prev.timestamp === curr.timestamp;
persistStateIntoHyperbee$(hyperbeeInstance, myElfStore, { distinct: customDistinct }).subscribe();loadStateThenPersistStateFromHyperbee$
import { loadStateThenPersistStateFromHyperbee$ } from "elf-hyperbee-persist";Combines loadStateFromHyperbee$ and persistStateIntoHyperbee$ in sequence.
Parameters:
hyperbee: The Hyperbee instance.elfStore: The Elf store to synchronize.options.prefix(default:"state"): If provided, applies a prefix to stored and retrieved keys.options.debounce(default:1000): Debounce time before persisting changes.options.cas(default: a deep equality check): A compare-and-swap (CAS) function that determines whether an entry should be updated in Hyperbee.- Accepts two parameters:
prev(previous entry) andcurr(new entry). - Should return
trueif the entry should be updated.
- Accepts two parameters:
options.distinct(default: a deep equality check): A function that determines whether state updates are considered distinct.- Used in
distinctUntilChangedto filter redundant updates. - Accepts two consecutive state values and should return
trueif they are the same (i.e., no need to update).
- Used in
Returns:
An RxJS observable that first loads the state and then starts persisting subsequent changes.
Example Usage:
// Using prefixed keys
loadStateThenPersistStateFromHyperbee$(hyperbeeInstance, myElfStore, { prefix: "gameState" }).subscribe();
// Using non-prefixed keys
loadStateThenPersistStateFromHyperbee$(hyperbeeInstance, myElfStore, { prefix: null }).subscribe();Utilities
stringStringIndexEncoding
import { stringStringIndexEncoding } from "elf-hyperbee-persist";A utility that provides encoding for string-based Hyperbee keys.
deepEqual
import { deepEqual } from "elf-hyperbee-persist";Performs a deep equality check between two objects to detect changes efficiently.
Example:
deepEqual({ a: 1, b: 2 }, { a: 1, b: 2 }); // true
deepEqual({ a: 1 }, { a: 1, b: 2 }); // falsepairwiseStartWith
import { pairwiseStartWith } from "elf-hyperbee-persist";An RxJS operator that emits previous and current values, starting with an initial state.
Example:
myObservable.pipe(pairwiseStartWith(initialState));How It Works
State Loading:
loadStateFromHyperbee$reads stored state from Hyperbee.- The state is merged into an RxJS Elf store.
- Supports both prefixed
[prefix, key]structures and direct keys.
State Watching & Persistence:
persistStateIntoHyperbee$listens for changes in the Elf store.- Uses
deepEqualto avoid unnecessary writes. - Debounces updates to optimize performance.
- Saves only changed entries into Hyperbee.
- Supports direct key storage when
prefixisnull.
Full Integration:
loadStateThenPersistStateFromHyperbee$ensures that state is first loaded before persistence starts.
License
This project is released under the MIT License.