### Synchronous Storage Adapter Example (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/README.md Demonstrates a basic synchronous storage adapter using `localStorage`. This example is simplified and lacks serialization, deserialization, and edge case handling. It shows how to define `get` and `set` functions for persistence. ```javascript import { createStore } from 'effector' import { persist } from 'effector-storage' const adapter = (key) => ({ get: () => localStorage.getItem(key), set: (value) => localStorage.setItem(key, value), }) const store = createStore('', { name: 'store' }) persist({ store, adapter }) // <- use adapter ``` -------------------------------- ### Install effector-storage using package managers Source: https://github.com/yumauri/effector-storage/blob/main/README.md Instructions for installing the effector-storage package using popular package managers like pnpm, yarn, and npm. ```bash # using `pnpm` ↓ $ pnpm add effector-storage # using `yarn` ↓ $ yarn add effector-storage # using `npm` ↓ $ npm install --save effector-storage ``` -------------------------------- ### Build Custom Storage Adapters with Effector Source: https://context7.com/yumauri/effector-storage/llms.txt Demonstrates how to create custom storage adapters by implementing the StorageAdapter interface. Examples include adapters with expiration and external update notifications. ```javascript import { createStore } from 'effector' import { persist } from 'effector-storage' // Adapter with expiration const expiringAdapter = (timeout) => (key, update) => ({ get() { const item = localStorage.getItem(key) if (item === null) return undefined const { time, value } = JSON.parse(item) if (time + timeout * 1000 < Date.now()) return undefined return value }, set(value) { localStorage.setItem(key, JSON.stringify({ time: Date.now(), value })) }, }) const $session = createStore(null, { name: 'session' }) persist({ store: $session, adapter: expiringAdapter(3600), // 1 hour expiry key: 'auth_session', }) // Adapter with external update notifications const realtimeAdapter = (key, update) => { // Listen for WebSocket updates socket.on(`update:${key}`, (newValue) => { update(newValue) // Triggers store update }) return { get: (raw) => raw ?? fetchFromServer(key), set: (value) => sendToServer(key, value), } } ``` -------------------------------- ### Import Query Adapter (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/query/README.md Provides examples of how to import the `query` function, which is used to create a `StorageAdapter` for the query string. It shows two valid import paths. ```javascript import { query } from 'effector-storage' // or import { query } from 'effector-storage/query' ``` -------------------------------- ### Asynchronous Storage Adapter Example (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/README.md Illustrates an asynchronous storage adapter using `@react-native-async-storage/async-storage`. This example is also simplified. For React Native, it's recommended to use the dedicated adapter from `effector-storage-extras`. ```javascript import AsyncStorage from '@react-native-async-storage/async-storage' import { createStore } from 'effector' import { persist } from 'effector-storage' const adapter = (key) => ({ get: async () => AsyncStorage.getItem(key), set: async (value) => AsyncStorage.setItem(key, value), }) const store = createStore('', { name: '@store' }) persist({ store, adapter }) // <- use adapter ``` -------------------------------- ### Domain Integration for Automatic Persistence Source: https://context7.com/yumauri/effector-storage/llms.txt Allows automatic persistence of all stores created within an Effector domain. This simplifies persistence setup for related stores. ```javascript import { createDomain } from 'effector' import { persist } from 'effector-storage/local' const app = createDomain('app') // Auto-persist all domain stores app.onCreateStore((store) => { persist({ store }) }) // These stores are automatically persisted const $counter = app.createStore(0, { name: 'counter' }) const $theme = app.createStore('light', { name: 'theme' }) // localStorage keys: "counter", "theme" ``` -------------------------------- ### URL Query Persistence with Effector-Storage and Data Fetching Source: https://github.com/yumauri/effector-storage/blob/main/src/query/README.md Illustrates a pattern for synchronizing an Effector store with URL query parameters using `effector-storage/query`, and then triggering a data fetch effect based on changes in that store. The example serializes an entity's ID to a string for the URL and uses `sample` to trigger `fetchEntityFx` when the ID changes. ```javascript import { persist } from 'effector-storage/query' import { createStore, sample } from 'effector' // Assume fetchEntityFx is defined elsewhere // const fetchEntityFx = ... const $entity = createStore(null).on( fetchEntityFx.doneData, (_, entity) => entity ) // ~ serialization down to plain `id` const $id = $entity.map((entity) => `${entity.id}`) persist({ store: $id, key: 'id' }) // in case of query string change -> fetch new entity by new id sample({ source: $id, target: fetchEntityFx, }) ``` -------------------------------- ### Storage Adapter with External Updates (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/README.md Shows how to create a storage adapter that can be updated from external sources, such as browser `storage` events. The `update` function is crucial here, allowing the adapter to inform the effector store about external changes, which in turn triggers the `get` function. ```javascript import { createStore } from 'effector' import { persist } from 'effector-storage' const adapter = (key, update) => { addEventListener('storage', (event) => { if (event.key === key) { // kick update // this will call `get` function from below ↓ // wrapped in Effect, to handle any errors update(event.newValue) } }) return { // `get` function will receive `newValue` argument // from `update`, called above ↑ get: (newValue) => newValue || localStorage.getItem(key), set: (value) => localStorage.setItem(key, value), } } const store = createStore('', { name: 'store' }) persist({ store, adapter }) // <- use adapter ``` -------------------------------- ### Change URL Update Method (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/query/README.md Illustrates how to change the method used for updating the URL query string. By default, `pushState` is used. This example shows how to use `replaceState` for updating the URL without adding a new history item. ```javascript import { persist, replaceState } from 'effector-storage/query' // use `history.replaceState` to change query string persist({ store: $id, key: 'id', method: replaceState }) ``` -------------------------------- ### Custom Serialization and Deserialization for Date Objects Source: https://github.com/yumauri/effector-storage/blob/main/src/local/README.md Provides an example of how to implement custom `serialize` and `deserialize` functions for persisting a `Date` object in localStorage. This ensures that the date can be correctly stored as a string and then restored as a `Date` object. ```javascript import { persist } from 'effector-storage/local' const $date = createStore(new Date(), { name: 'date' }) persist({ store: $date, serialize: (date) => String(date.getTime()), deserialize: (timestamp) => new Date(Number(timestamp)), }) ``` -------------------------------- ### Debounce Session Storage Writes with `source`/`target` (Effector-Storage/Session) Source: https://github.com/yumauri/effector-storage/blob/main/src/session/README.md This example shows an alternative method for debouncing sessionStorage writes using the `source`/`target` form of `persist` along with `patronum/debounce`. It's useful when you need more control over the event triggering the debounced update. Requires `effector-storage` and `patronum` libraries. ```javascript import { debounce } from 'patronum/debounce' import { persist } from 'effector-storage/session' const setWidth = createEvent() const setWidthDebounced = debounce({ source: setWidth, timeout: 100, }) const $windowWidth = createStore(window.innerWidth) // .on(setWidth, (_, width) => width) persist({ source: setWidthDebounced, target: $windowWidth, key: 'width', }) // `setWidth` event will be called on every 'resize' event, // `$windowWidth` store will be updated accordingly // but `sessionStorage` will be updated only on debounced event window.addEventListener('resize', () => { setWidth(window.innerWidth) }) ``` -------------------------------- ### Integrate Farfetched Cache Adapter with farcached Source: https://github.com/yumauri/effector-storage/blob/main/src/tools/README.md The `farcached` utility enables the use of Farfetched cache adapters (like `localStorageCache`) with `effector-storage`'s `persist` function. This allows leveraging Farfetched's cache invalidation logic, such as `maxAge`, within your storage persistence setup. ```javascript import { persist, farcached } from 'effector-storage' import { localStorageCache } from '@farfetched/core' persist({ store: $store, adapter: farcached(localStorageCache({ maxAge: '15m' })), key: 'store', }) ``` -------------------------------- ### Select Adapters Dynamically with Either in Effector Storage Source: https://context7.com/yumauri/effector-storage/llms.txt The 'either' tool enables dynamic selection of storage adapters based on environment support, which is particularly useful for Server-Side Rendering (SSR) or environments where certain storage mechanisms might not be available. Dependencies include 'effector', 'effector-storage', and 'effector-storage/tools'. ```javascript import { createStore } from 'effector' import { persist, local, log } from 'effector-storage' import { either } from 'effector-storage/tools' // Use localStorage in browser, log adapter in Node.js const $store = createStore(0, { name: 'store' }) persist({ store: $store, adapter: either(local, log), key: 'counter', }) // In browser: uses localStorage // In Node.js: logs get/set operations to console ``` -------------------------------- ### Import Nil Adapter (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/nil/README.md Shows two ways to import the 'nil' adapter from the effector-storage library. The first imports it directly from the main package, while the second imports it from the dedicated 'nil' module. ```javascript import { nil } from 'effector-storage' ``` ```javascript import { nil } from 'effector-storage/nil' ``` -------------------------------- ### Triggering Storage Updates with `pickup` in Effector Source: https://github.com/yumauri/effector-storage/blob/main/README.md Demonstrates how to use the `pickup` parameter with `effector-storage/session` to manually trigger updates from an external source when the store doesn't have built-in reaction mechanisms. This is useful when storage is updated by an external process. ```javascript import { createEvent, createStore } from 'effector' import { persist } from 'effector-storage/session' // event, which will be used to trigger update const pickup = createEvent() const store = createStore('', { name: 'store' }) persist({ store, pickup }) // <- set `pickup` parameter // --8<-- // when you are sure, that storage was updated, // and you need to update `store` from storage with new value pickup() ``` -------------------------------- ### Importing the Storage Adapter (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/storage/README.md This snippet shows the two ways to import the `storage` adapter from the `effector-storage` library. Both imports achieve the same result, allowing you to configure how your Effector stores interact with browser storage. ```javascript import { storage } from 'effector-storage' ``` ```javascript import { storage } from 'effector-storage/storage' ``` -------------------------------- ### Effector localStorage Adapter Initialization Source: https://github.com/yumauri/effector-storage/blob/main/src/local/README.md Illustrates how to import and initialize the `local` adapter function from `effector-storage` or `effector-storage/local`. ```javascript import { local } from 'effector-storage' or import { local } from 'effector-storage/local' ``` -------------------------------- ### Debounce localStorage Writes with Effector-Storage (Timeout Option - JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/local/README.md Starting from version 6.0.0 of effector-storage, you can directly use the `timeout` option within the `persist` function to debounce writes to localStorage. This provides a simpler, built-in way to throttle localStorage updates without external libraries like patronum. ```javascript import { persist } from 'effector-storage/local' persist({ store: $store, key: 'myStore', timeout: 500 // Writes to localStorage will be debounced with a 500ms delay }) ``` -------------------------------- ### Using the `storage` Factory for Custom Storage in Effector Source: https://github.com/yumauri/effector-storage/blob/main/README.md Explains how to use the `storage` factory from `effector-storage/storage` to create adapters for any object implementing the `Storage` interface (or just `getItem` and `setItem`). It outlines the available options for customization. ```javascript import { storage } from 'effector-storage/storage' ``` ```javascript adapter = storage(options) ``` -------------------------------- ### Import AsyncStorage Adapter for Effector Storage Source: https://github.com/yumauri/effector-storage/blob/main/src/async-storage/README.md Demonstrates two ways to import the asynchronous storage adapter from the 'effector-storage' library. This adapter is crucial for enabling persistence with asynchronous storage solutions. ```javascript import { asyncStorage } from 'effector-storage' ``` ```javascript import { asyncStorage } from 'effector-storage/async-storage' ``` -------------------------------- ### Importing the Log Adapter in JavaScript Source: https://github.com/yumauri/effector-storage/blob/main/src/log/README.md Shows two ways to import the log adapter. You can import it directly from 'effector-storage' or specifically from 'effector-storage/log'. This is used to configure the adapter's behavior. ```javascript import { log } from 'effector-storage' ``` ```javascript import { log } from 'effector-storage/log' ``` -------------------------------- ### Custom Storage Adapter with `pickup` Event in Effector Source: https://github.com/yumauri/effector-storage/blob/main/README.md Shows how to integrate the `pickup` event directly into a custom storage adapter for effector-storage. This allows the adapter to react to an Effector event and trigger a store update from the storage. ```javascript import { createEvent, createStore } from 'effector' import { persist } from 'effector-storage' // event, which will be used in adapter to react to const pickup = createEvent() const adapter = (key, update) => { // if `pickup` event was triggered -> call an `update` function // this will call `get` function from below ↓ // wrapped in Effect, to handle any errors pickup.watch(update) return { get: () => localStorage.getItem(key), set: (value) => localStorage.setItem(key, value), } } const store = createStore('', { name: 'store' }) persist({ store, adapter }) // <- use your adapter // --8<-- // when you are sure, that storage was updated, // and you need to force update `store` from storage with new value pickup() ``` -------------------------------- ### Initialize BroadcastChannel Adapter (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/broadcast/README.md This snippet shows how to import and initialize the `broadcast` adapter from `effector-storage`. The `broadcast` function returns a `StorageAdapter` instance. It accepts an optional `channel` option to specify the name of the BroadcastChannel to use, defaulting to 'effector-storage'. ```javascript import { broadcast } from 'effector-storage' // or import { broadcast } from 'effector-storage/broadcast' // Example usage with options: broadcast({ channel: 'my-custom-channel' }) ``` -------------------------------- ### Import Memory Storage Adapter for Effector Source: https://github.com/yumauri/effector-storage/blob/main/src/memory/README.md Shows how to import the `memory` storage adapter from `effector-storage` or specifically from `effector-storage/memory`. This adapter is used to configure memory-based persistence for Effector stores. ```javascript import { memory } from 'effector-storage' // or import { memory } from 'effector-storage/memory' ``` -------------------------------- ### Persist Store with Nil Adapter (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/nil/README.md Demonstrates how to use the 'nil' adapter with the 'persist' function from effector-storage to prevent a store from being persisted. This is useful for testing or when no actual storage is needed. ```javascript import { persist, nil } from 'effector-storage' // persist store `$counter` with nil adapter == do nothing persist({ adapter: nil, store: $counter, key: 'counter', }) ``` -------------------------------- ### Persist Store in Query String (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/query/README.md Demonstrates how to use the `persist` function from 'effector-storage/query' to synchronize an Effector store with a query string parameter. It shows basic usage and how to omit the `key` if the storage name is sufficient. Multiple stores persisted with the same key will be synchronized. ```javascript import { persist } from 'effector-storage/query' // persist store $id in query string with param name 'id' persist({ store: $id, key: 'id' }) // if your storage has a name, you can omit `key` field persist({ store: $id }) ``` -------------------------------- ### Select Between Adapters with either Source: https://github.com/yumauri/effector-storage/blob/main/src/tools/README.md The `either` utility allows selecting between two storage adapters. It returns the first adapter provided unless it's a 'no-op' adapter, in which case it returns the second adapter. This is beneficial for environments with differing storage capabilities, like server-side rendering. ```javascript import { persist, either, local, log } from 'effector-storage' // - in browser environment will persist // store `$counter` in `localStorage` with key 'counter' // - in node environment will just log persist activity persist({ adapter: either(local, log), store: $counter, key: 'counter', }) ``` -------------------------------- ### Make Synchronous Adapter Asynchronous with async Source: https://github.com/yumauri/effector-storage/blob/main/src/tools/README.md The `async` utility transforms a synchronous storage adapter into an asynchronous one. This is useful to prevent immediate synchronous store updates upon initialization, allowing for controlled asynchronous behavior. It takes an adapter as input and returns a new asynchronous adapter. ```javascript import { persist, async, local } from 'effector-storage' persist({ adapter: async(local), store: $counter, done: valueRestored, }) // add watcher AFTER persist valueRestored.watch(({ value }) => console.log(value)) ``` -------------------------------- ### Import Core Persist Function (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/README.md Demonstrates importing the core `persist` function from the `effector-storage` library. This function allows for more advanced usage by accepting a custom storage adapter. ```javascript import { persist } from 'effector-storage' ``` -------------------------------- ### Effector Storage Persistence Formulae (Effector) Source: https://github.com/yumauri/effector-storage/blob/main/README.md Provides the core formulae for using `persist` from `effector-storage/`. It outlines two primary ways to use `persist`: with a single `store` or with `source` and `target` units. This highlights the flexibility in synchronizing Effector units with storage. ```javascript import { persist } from 'effector-storage/' // persist({ store, ...options }): Subscription // persist({ source, target, ...options }): Subscription ``` -------------------------------- ### Persist Store in Memory with Effector Storage Source: https://github.com/yumauri/effector-storage/blob/main/src/memory/README.md Demonstrates how to use the `persist` function from `effector-storage/memory` to synchronize an Effector store with a memory-based storage. This is useful for testing and ensuring data is available in memory. ```javascript import { persist } from 'effector-storage/memory' // persist store $counter with key 'counter' persist({ store: $counter, key: 'counter' }) // if your storage has a name, you can omit `key` field persist({ store: $counter }) ``` -------------------------------- ### Session Storage Adapter Initialization Source: https://github.com/yumauri/effector-storage/blob/main/src/session/README.md Shows how to import and use the `session` adapter function from 'effector-storage' or 'effector-storage/session'. This adapter provides a `StorageAdapter` interface for interacting with sessionStorage, configurable with options like synchronization, serialization, and timeouts. ```javascript import { session } from 'effector-storage' // or import { session } from 'effector-storage/session' ``` -------------------------------- ### Persist Store with Log Adapter in JavaScript Source: https://github.com/yumauri/effector-storage/blob/main/src/log/README.md Demonstrates how to use the log adapter to persist a store. The adapter logs messages related to the persistence operation but does not actually store data. It requires importing `persist` and `log` from 'effector-storage'. ```javascript import { persist, log } from 'effector-storage' // persist store `$counter` with log adapter == do nothing + print messages persist({ adapter: log, store: $counter, key: 'counter', }) ``` -------------------------------- ### Either Adapter Utility Source: https://github.com/yumauri/effector-storage/blob/main/src/tools/README.md The `either` utility function allows you to specify a primary adapter and a fallback adapter. It will use the primary adapter unless it's a 'no-op' adapter (marked with `noop: true`), in which case it will use the secondary adapter. This is beneficial for code that runs in different environments, like server-side rendering. ```APIDOC ## `either` Adapter Utility ### Description Given two adapters, returns the first one, or the second one if the first one is a 'no-op' adapter. Useful for environment-specific storage solutions. ### Method `either(primaryAdapter, fallbackAdapter)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript import { persist, either, local, log } from 'effector-storage' persist({ adapter: either(local, log), store: $counter, key: 'counter', }) ``` ### Response #### Success Response (200) N/A (This is a utility function, not an API endpoint) #### Response Example N/A ### Notes - The fallback is only used if the primary adapter is explicitly marked as `noop: true` or is inherently a no-op adapter. - `either` does not fallback in case of read/write errors, only if the adapter is unsupported in the environment. ``` -------------------------------- ### Async Adapter Utility Source: https://github.com/yumauri/effector-storage/blob/main/src/tools/README.md The `async` utility function modifies a synchronous storage adapter to behave asynchronously. This is useful for preventing synchronous operations from immediately setting store values and triggering callbacks, especially with storage mechanisms like localStorage. ```APIDOC ## `async` Adapter Utility ### Description Makes a synchronous storage adapter asynchronous. This prevents immediate synchronous setting of store values and callback triggers when `persist` is called. ### Method `async(adapter)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript import { persist, async, local } from 'effector-storage' persist({ adapter: async(local), store: $counter, done: valueRestored, }) // add watcher AFTER persist valueRestored.watch(({ value }) => console.log(value)) ``` ### Response #### Success Response (200) N/A (This is a utility function, not an API endpoint) #### Response Example N/A ``` -------------------------------- ### Make Adapter Asynchronous with effector-storage/tools async Source: https://context7.com/yumauri/effector-storage/llms.txt Converts synchronous storage adapters to asynchronous ones, ensuring consistent behavior and preventing blocking operations. This is useful for integrating synchronous adapters into asynchronous workflows. ```javascript import { createStore } from 'effector' import { persist, local } from 'effector-storage' import { async } from 'effector-storage/tools' const $store = createStore(0, { name: 'store' }) // localStorage operations become async persist({ store: $store, adapter: async(local), key: 'counter', }) ``` -------------------------------- ### Create Custom Persist Function with Key Prefix (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/README.md Illustrates using the `createPersist` factory to generate a custom `persist` function with a predefined key prefix. This is useful for namespacing storage keys across different parts of an application. ```javascript import { createPersist } from 'effector-storage/local' const persist = createPersist({ keyPrefix: 'app/', }) // --- persist({ store: $store1, key: 'store1', // localStorage key will be `app/store1` }) persist({ store: $store2, key: 'store2', // localStorage key will be `app/store2` }) ``` -------------------------------- ### Persist Effector Store with Browser Storage (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/storage/README.md This snippet demonstrates how to use the `persist` function from `effector-storage` to synchronize an Effector store with browser storage. It requires importing `persist` and `storage` from the library. The `storage` adapter is configured with a reference to `localStorage`, and the store to be persisted along with a unique key are provided. ```javascript import { persist } from 'effector-storage' import { storage } from 'effector-storage/storage' // persist store `$counter` in `localStorage` with key 'counter' persist({ adapter: storage({ storage: () => localStorage }), store: $counter, key: 'counter', }) ``` -------------------------------- ### Throttle Query String Updates with Timeout (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/query/README.md Shows how to use the `timeout` option to throttle updates to the query string. This batches multiple simultaneous updates into a single history record, preventing excessive history entries and potential cyclic updates. ```javascript persist({ store: $page, key: 'page', timeout: 10 }) persist({ store: $count, key: 'count', timeout: 10 }) ``` -------------------------------- ### Create Custom Storage Adapters with effector-storage storage Source: https://context7.com/yumauri/effector-storage/llms.txt Factory function to create adapters for any Storage-compatible interface, including localStorage, sessionStorage, or custom implementations. Supports serialization, deserialization, and synchronization options. ```javascript import { createStore } from 'effector' import { persist, storage } from 'effector-storage' // Custom storage adapter with encryption const encryptedStorage = storage({ storage: () => localStorage, serialize: (value) => btoa(JSON.stringify(value)), deserialize: (value) => JSON.parse(atob(value)), sync: true, // Listen for storage events timeout: 100, // Debounce writes }) const $secret = createStore('', { name: 'secret' }) persist({ store: $secret, adapter: encryptedStorage, key: 'encrypted_data', }) ``` -------------------------------- ### React Native AsyncStorage Adapter with effector-storage asyncStorage Source: https://context7.com/yumauri/effector-storage/llms.txt Creates adapters specifically for asynchronous storage interfaces like React Native's AsyncStorage. This allows seamless integration of React Native's storage solutions with Effector. ```javascript import { createStore } from 'effector' import { persist, asyncStorage } from 'effector-storage' import AsyncStorage from '@react-native-async-storage/async-storage' const adapter = asyncStorage({ storage: () => AsyncStorage, }) const $userData = createStore({}, { name: 'userData' }) persist({ store: $userData, adapter, key: 'user_data', }) ``` -------------------------------- ### Persist Store with BroadcastChannel Adapter (JavaScript) Source: https://github.com/yumauri/effector-storage/blob/main/src/broadcast/README.md This snippet demonstrates how to use the `persist` function from `effector-storage/broadcast` to synchronize an Effector store across different browsing contexts. It takes the store and a key as arguments. The key is used to identify the channel for synchronization. If no key is provided, a default channel name is used. ```javascript import { persist } from 'effector-storage/broadcast' // sync store `$counter` between different contexts with key 'counter' persist({ store: $counter, key: 'counter' }) // if your storage has a name, you can omit `key` field persist({ store: $counter }) ``` -------------------------------- ### Persist Effector Store in localStorage Source: https://github.com/yumauri/effector-storage/blob/main/src/local/README.md Demonstrates how to use the `persist` function from `effector-storage/local` to save an Effector store's state to the browser's localStorage. It shows basic usage and how to specify a custom key. ```javascript import { persist } from 'effector-storage/local' // persist store $counter in `localStorage` with key 'counter' persist({ store: $counter, key: 'counter' }) // if your storage has a name, you can omit `key` field persist({ store: $counter }) ``` -------------------------------- ### Persist Store in Domain onCreateStore Hook (Effector) Source: https://github.com/yumauri/effector-storage/blob/main/README.md Demonstrates how to use the `persist` function from `effector-storage/local` within an Effector domain's `onCreateStore` hook. This allows all stores created within the domain to be automatically persisted to `localStorage` using their names as keys. It requires `effector` and `effector-storage/local`. ```javascript import { createDomain } from 'effector' import { persist } from 'effector-storage/local' const app = createDomain('app') // this hook will persist every store, created in domain, // in `localStorage`, using stores' names as keys app.onCreateStore((store) => persist({ store })) const $store = app.createStore(0, { name: 'store' }) ``` -------------------------------- ### Import persist function from effector-storage/local Source: https://github.com/yumauri/effector-storage/blob/main/src/local/README.md Shows the import statement required to use the `persist` function for localStorage persistence. ```javascript import { persist } from 'effector-storage/local' ``` -------------------------------- ### Persist Store Parts with Source/Target Pattern in Effector Source: https://context7.com/yumauri/effector-storage/llms.txt This pattern allows for granular control over data persistence by specifying source and target units. It's useful for scenarios where only specific parts of a store need to be persisted or when transformations are required before storage. Dependencies include 'effector' and 'effector-storage/local'. ```javascript import { createStore, createEvent } from 'effector' import { persist } from 'effector-storage/local' // Persist only part of a store const setX = createEvent() const setY = createEvent() const $coords = createStore({ x: 0, y: 0 }) .on(setX, ({ y }, x) => ({ x, y })) .on(setY, ({ x }, y) => ({ x, y })) // Persist X coordinate separately persist({ source: $coords.map(({ x }) => x), target: setX, key: 'coord_x', }) // Persist Y coordinate separately persist({ source: $coords.map(({ y }) => y), target: setY, key: 'coord_y', }) // Event-based persistence const updateToken = createEvent() const tokenUpdated = createEvent() persist({ source: updateToken, target: tokenUpdated, key: 'api_token', }) ``` -------------------------------- ### Custom Serialization/Deserialization for Number IDs with Effector-Storage Source: https://github.com/yumauri/effector-storage/blob/main/src/query/README.md Demonstrates how to use custom `serialize` and `deserialize` functions with `effector-storage/query` to persist a number store to the URL. This is useful when the store's type is not a plain string. The `serialize` function converts the number to a string, and `deserialize` converts it back to a number. ```typescript import { persist } from 'effector-storage/query' import { createStore } from 'effector/effector-core' const $id = createStore(null) persist({ store: $id, key: 'id', serialize: (id) => String(id), deserialize: (id) => Number(id), }) ``` -------------------------------- ### Persist Store with Query String using effector-storage Source: https://context7.com/yumauri/effector-storage/llms.txt Synchronizes Effector store values with URL query parameters. This allows for bookmarkable states and navigation. It supports custom methods like `pushState` and `replaceState` for controlling history entries, and custom serialization for non-string values. ```javascript import { createStore } from 'effector' import { persist, pushState, replaceState } from 'effector-storage/query' // Basic query string persistence const $page = createStore('1', { name: 'page' }) persist({ store: $page, key: 'page' }) // URL becomes: ?page=2 when $page changes // Use replaceState to avoid history entries const $filter = createStore('all', { name: 'filter' }) persist({ store: $filter, key: 'filter', method: replaceState }) // With serialization for numeric values const $limit = createStore(10, { name: 'limit' }) persist({ store: $limit, key: 'limit', serialize: (n) => String(n), deserialize: (s) => Number(s), }) // Batch multiple query param updates with timeout const $sortBy = createStore('name', { name: 'sort' }) const $sortOrder = createStore('asc', { name: 'order' }) persist({ store: $sortBy, key: 'sort', timeout: 0 }) persist({ store: $sortOrder, key: 'order', timeout: 0 }) // Single URL update: ?sort=date&order=desc ``` -------------------------------- ### Create Custom Persist Function with Defaults in Effector Source: https://context7.com/yumauri/effector-storage/llms.txt The 'createPersist' factory function allows you to create a custom persist function with predefined adapter options, such as key prefixes. This is useful for namespacing storage keys across your application. Dependencies include 'effector' and 'effector-storage/local'. ```javascript import { createStore } from 'effector' import { createPersist } from 'effector-storage/local' // Create namespaced persist function const persist = createPersist({ keyPrefix: 'myapp/', }) const $store1 = createStore(0, { name: 'store1' }) const $store2 = createStore('', { name: 'store2' }) persist({ store: $store1, key: 'counter' }) // localStorage key: "myapp/counter" persist({ store: $store2, key: 'name' }) // localStorage key: "myapp/name" ``` -------------------------------- ### Handle Persistence Events with Done/Fail/Finally in Effector Source: https://context7.com/yumauri/effector-storage/llms.txt Monitor persistence operations using callback units for success ('done'), failure ('fail'), and completion ('finally') events. This allows for logging, error handling, or triggering subsequent actions based on the outcome of storage operations. Dependencies include 'effector' and 'effector-storage/local'. ```javascript import { createStore, createEvent, createEffect } from 'effector' import { persist } from 'effector-storage/local' const $data = createStore({}, { name: 'data' }) const onDone = createEvent() const onFail = createEvent() const onFinally = createEvent() persist({ store: $data, key: 'app_data', done: onDone, fail: onFail, finally: onFinally, }) onDone.watch(({ key, operation, value }) => { console.log(`${operation} succeeded for ${key}:`, value) // Output: "get succeeded for app_data: {}" }) onFail.watch(({ key, operation, error }) => { console.error(`${operation} failed for ${key}:`, error) }) onFinally.watch(({ status, key, operation }) => { console.log(`${operation} ${status} for ${key}`) }) ``` -------------------------------- ### Persisting Part of an Effector Store Source: https://github.com/yumauri/effector-storage/blob/main/README.md Demonstrates how to persist only a specific part of an Effector store using the `source` and `target` options with the `persist` function. This method requires careful handling to avoid infinite loops, especially when persisting non-plain values. ```javascript import { persist } from 'effector-storage/local' const setX = createEvent() const setY = createEvent() const $coords = createStore({ x: 123, y: 321 }) .on(setX, ({ y }, x) => ({ x, y })) .on(setY, ({ x }, y) => ({ x, y })) // persist X coordinate in `localStorage` with key 'x' persist({ source: $coords.map(({ x }) => x), target: setX, key: 'x', }) // persist Y coordinate in `localStorage` with key 'y' persist({ source: $coords.map(({ y }) => y), target: setY, key: 'y', }) ``` -------------------------------- ### Persist Effector Store with AsyncStorage Source: https://github.com/yumauri/effector-storage/blob/main/src/async-storage/README.md Persists an Effector store using the provided asynchronous storage adapter. It takes the storage adapter, the store itself, and a unique key for persistence. If multiple stores share the same key, they will be synchronized automatically. ```javascript import { persist, asyncStorage } from 'effector-storage' import AsyncStorage from '@react-native-async-storage/async-storage' // persist store `$counter` in `localStorage` with key 'counter' persist({ adapter: asyncStorage({ storage: () => AsyncStorage }), store: $counter, key: 'counter', }) ``` -------------------------------- ### Farcached Adapter Utility Source: https://github.com/yumauri/effector-storage/blob/main/src/tools/README.md The `farcached` utility function wraps cache adapters from `@farfetched/core` to be used with `effector-storage`'s `persist` function. This enables advanced cache invalidation logic and integration with Farfetched's caching mechanisms. ```APIDOC ## `farcached` Adapter Utility ### Description Wraps a `@farfetched/core` cache adapter to be compatible with `effector-storage`'s `persist` function. Enables cache invalidation logic and integration with Farfetched's caching system. ### Method `farcached(farfetchedCacheAdapter)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript import { persist, farcached } from 'effector-storage' import { localStorageCache } from '@farfetched/core' persist({ store: $store, adapter: farcached(localStorageCache({ maxAge: '15m' })), key: 'store', }) ``` ### Response #### Success Response (200) N/A (This is a utility function, not an API endpoint) #### Response Example N/A ### Supported Farfetched Cache Adapters - `inMemoryCache` - `sessionStorageCache` - `localStorageCache` - `voidCache` (no-op) ``` -------------------------------- ### Sync Effector stores across browsing contexts with BroadcastChannel Source: https://github.com/yumauri/effector-storage/blob/main/README.md Enables synchronization of Effector stores across different browsing contexts such as tabs, windows, and web workers using the BroadcastChannel API. Import `persist` from `'effector-storage/broadcast'` to enable this functionality. ```javascript import { persist } from 'effector-storage/broadcast' // persist store `$user` across contexts with key 'user' persist({ store: $user, key: 'user' }) ```