0.7.0 • Published 5 months ago

@cubux/effector-persistent v0.7.0

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

@cubux/effector-persistent

NPM latest

Persist data in effector store.

import { createStore } from "effector";
import { withPersistent } from "@cubux/effector-persistent";
import { createLocalStorageDriver } from "@cubux/storage-driver";

const $accessToken = withPersistent(
  createStore(""),
  createLocalStorageDriver(),
  "accessToken"
);

Install

npm i @cubux/effector-persistent

API

See also @cubux/storage-driver. It supports localStorage/sessionStorage and indexedDB.

withPersistent()

Register persistent data handling for the given store with the given driver. Data from store will be stored in driver with the given key. Function returns input store, so it can be used inline.

Type of store can be Store only when wakeUp options is defined. Otherwise a StoreWritable is needed.

function withPersistent<Key, Value, Serialized = Value>(
  store:    Store<Value>
          | StoreWritable<Value>,
  driver:   StoreDriverSingle<Key, Serialized>
          | Promise<StoreDriverSingle<Key, Serialized>>,
  key:      Key,
  options?: WithPersistentOptions<Value, Value, Serialized>
): typeof store

Example:

import { createStore } from "effector";
import { withPersistent } from "@cubux/effector-persistent";
import { createLocalStorageDriver } from "@cubux/storage-driver";

const lsDriver = createLocalStorageDriver();
const $storeA = withPersistent(createStore(0), lsDriver, "keyA");
const $storeB = withPersistent(createStore(""), lsDriver, "keyB");

In the example above $storeA and $storeB will use localStorage for persistent data with keys "persistent:keyA" and "persistent:keyB" respectively.

withPersistentMap()

Register persistent data handling for the given ReadonlyMap store with the given driver. Data from store will be stored in driver with corresponding keys from ReadonlyMap. Function returns input store, so it can be used inline.

Type of store can be Store only when wakeUp options is defined. Otherwise a StoreWritable is needed.

function withPersistentMap<Key, Value, Serialized = Value>(
  store:    Store<ReadonlyMap<Key, Value>>
          | StoreWritable<ReadonlyMap<Key, Value>>,
  driver:   StoreDriver<Key, Serialized>
          | Promise<StoreDriver<Key, Serialized>>,
  options?: WithPersistentOptions<ReadonlyMap<Key, Value>, Value, Serialized>
): typeof store

Under the hood on every store change it will detect changes in underlying Map entries and will send to driver only those was changed.

Notice: Serialization when used with options will be applied to individual values Value rather than to whole Map<Key, Value>.

Example:

import { createStore } from "effector";
import { withPersistentMap } from "@cubux/effector-persistent";
import { createLocalStorageDriver } from "@cubux/storage-driver";

const $storeMap = withPersistentMap(
  createStore<ReadonlyMap<string, number>>(new Map()),
  createLocalStorageDriver()
);

In the example above $storeMap will use localStorage for persistent data with keys starting with "persistent:", so every entry from ReadonlyMap will have its own row in localStorage.

interface WithPersistentFlushEvent

A payload for flush events.

PropertyTypeDescription
idsymbolIdentifier for current flush flow

interface WithPersistentFlushFailEvent

A payload for flush events.

This interface extends WithPersistentFlushEvent with the following additional properties:

PropertyTypeDescription
errorunknownReason of the failure

interface WithPersistentOptions

Common options for persistent storage.

interface WithPersistentOptions<
  State = any,
  Value = State,
  Serialized = Value
>
OptionsTypeDefaultDescription
flushDelaynumberundefinedDebounce subsequent store updates and flush only after latest change. If set to undefined (default), no debounce will be used, so every store update will be flushed to driver.
onFlushStartEventCallable<WithPersistentFlushEvent>undefinedAn Event to trigger before flushing to driver. An id in payload can be used in all the rest "flush" events to identify the flow when it's needed.
onFlushDoneEventCallable<WithPersistentFlushEvent>undefinedAn Event to trigger when flush succeeds. An id in payload refers to id from appropriate onFlushStart payload.
onFlushFailEventCallable<WithPersistentFlushFailEvent>undefinedAn Event to trigger when flush fails. An id in payload refers to id from appropriate onFlushStart payload.
onFlushFinallyEventCallable<WithPersistentFlushEvent>undefinedAn Event to trigger before flushing to driver. This al always triggering after either onFlushDone or onFlushFail. An id in payload refers to id from appropriate onFlushStart payload.
readOnlyEventCallable<boolean>undefinedA filter Store to disable writes to Driver.
wakeUpStoreWritable<State> | ((state: State) => void)undefinedAlternative target which will receive initial state read from driver on initialization. When undefined, the source StoreWritable will be used.
serialize(input: Value) => Serialized | Promise<Serialized>undefinedSerialization before writing data to driver.
unserialize(output: Serialized) => Value | Promise<Value>undefinedUnserialization after reading data from driver.

Helper API

flushDelayed()

Setup delayed flushes from source unit to target unit with whe given debounce interval.

Prefer patronum debounce() instead.

function flushDelayed<T>(options: Options<T>): (() => void);

It takes options described below and returns a function to stop watching and interrupt planned flush.

OptionsTypeDefaultDescription
sourceStore<T> | Event<T>RequiredSource unit to watch
target(payload: T) => voidRequiredReceiver to flush data to
flushDelaynumber | Store<number>1000Debounce timeout to await before flush
filterStore<boolean>undefinedWhen specified, flushes will work only when this filter Store is true

Actual flush target will be called only after source unit will stop triggering for at least duration in flushDelay. That is while source is keeping triggering continuous within this duration, flush target will never be called.

When flushDelay is Store<number>, it's value will take effect only on next source update.

When filter is used, it will abort current planned flush, when its value becomes false.