RxJS Elf state persistence and synchronization with Hyperbee
npm install elf-hyperbee-persistelf-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.
- 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.
---
Install the package via npm:
``sh`
npm install elf-hyperbee-persist
---
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.
- Bare Environment Compatibility:
- Can run in environments without traditional Node.js dependencies.
- Uses bare:test to ensure functionality in Bare-based runtimes.
#### Running Tests for Both Environments
To ensure compatibility, both standard and Bare tests are included:
`shStandard Node.js test
npm test
---
API
$3
`js
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 prefix is null, keys are assumed to be stored as direct keys instead of [prefix, key].#### Returns:
An RxJS observable that, when subscribed to, loads the state into the Elf store.
#### Example Usage:
`js
// Using prefixed keys
loadStateFromHyperbee$(hyperbeeInstance, myElfStore, { prefix: "gameState" }).subscribe();// Using non-prefixed keys
loadStateFromHyperbee$(hyperbeeInstance, myElfStore, { prefix: null }).subscribe();
`$3
`js
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 prefix is null, stores keys directly without structuring them as arrays.
- 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) and curr (new entry).
- Should return true if the entry should be updated.
- options.distinct _(default: a deep equality check)_: A function that determines whether state updates are considered distinct.
- Used in distinctUntilChanged to filter redundant updates.
- Accepts two consecutive state values and should return true if they are the same (i.e., no need to update).#### Returns:
An RxJS observable that processes state updates and saves them to Hyperbee.
#### Example Usage:
`js
// 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();
`---
$3
`js
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) and curr (new entry).
- Should return true if the entry should be updated.
- options.distinct _(default: a deep equality check)_: A function that determines whether state updates are considered distinct.
- Used in distinctUntilChanged to filter redundant updates.
- Accepts two consecutive state values and should return true if they are the same (i.e., no need to update).#### Returns:
An RxJS observable that first loads the state and then starts persisting subsequent changes.
#### Example Usage:
`js
// Using prefixed keys
loadStateThenPersistStateFromHyperbee$(hyperbeeInstance, myElfStore, { prefix: "gameState" }).subscribe();// Using non-prefixed keys
loadStateThenPersistStateFromHyperbee$(hyperbeeInstance, myElfStore, { prefix: null }).subscribe();
`---
Utilities
$3
`js
import { stringStringIndexEncoding } from "elf-hyperbee-persist";
`
A utility that provides encoding for string-based Hyperbee keys.---
$3
`js
import { deepEqual } from "elf-hyperbee-persist";
`
Performs a deep equality check between two objects to detect changes efficiently.#### Example:
`js
deepEqual({ a: 1, b: 2 }, { a: 1, b: 2 }); // true
deepEqual({ a: 1 }, { a: 1, b: 2 }); // false
`---
$3
`js
import { pairwiseStartWith } from "elf-hyperbee-persist";
`
An RxJS operator that emits previous and current values, starting with an initial state.#### Example:
`js
myObservable.pipe(pairwiseStartWith(initialState));
`---
How It Works
1. 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.2. State Watching & Persistence:
-
persistStateIntoHyperbee$ listens for changes in the Elf store.
- Uses deepEqual to avoid unnecessary writes.
- Debounces updates to optimize performance.
- Saves only changed entries into Hyperbee.
- Supports direct key storage when prefix is null.3. Full Integration:
-
loadStateThenPersistStateFromHyperbee$` ensures that state is first loaded before persistence starts.---
This project is released under the MIT License.