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-persist
Compatibility
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:test
to 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:test
API
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
prefix
isnull
, 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
prefix
isnull
, 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
true
if 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
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).
- 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
true
if 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
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).
- 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 }); // false
pairwiseStartWith
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
deepEqual
to avoid unnecessary writes. - Debounces updates to optimize performance.
- Saves only changed entries into Hyperbee.
- Supports direct key storage when
prefix
isnull
.
Full Integration:
loadStateThenPersistStateFromHyperbee$
ensures that state is first loaded before persistence starts.
License
This project is released under the MIT License.