{"id":44060626,"url":"https://github.com/cubux-net/effector-persistent","last_synced_at":"2026-02-08T01:35:13.368Z","repository":{"id":58688170,"uuid":"533153291","full_name":"cubux-net/effector-persistent","owner":"cubux-net","description":"Persist data in `effector` store.","archived":false,"fork":false,"pushed_at":"2024-07-22T13:04:59.000Z","size":53,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-27T16:56:32.647Z","etag":null,"topics":["effector","persistent","storage","store"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cubux-net.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-09-06T03:56:23.000Z","updated_at":"2024-07-22T13:03:08.000Z","dependencies_parsed_at":"2023-12-11T16:01:23.694Z","dependency_job_id":null,"html_url":"https://github.com/cubux-net/effector-persistent","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/cubux-net/effector-persistent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubux-net%2Feffector-persistent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubux-net%2Feffector-persistent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubux-net%2Feffector-persistent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubux-net%2Feffector-persistent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cubux-net","download_url":"https://codeload.github.com/cubux-net/effector-persistent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubux-net%2Feffector-persistent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29216089,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-08T00:10:47.190Z","status":"ssl_error","status_checked_at":"2026-02-08T00:10:43.589Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["effector","persistent","storage","store"],"created_at":"2026-02-08T01:35:12.744Z","updated_at":"2026-02-08T01:35:13.357Z","avatar_url":"https://github.com/cubux-net.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `@cubux/effector-persistent`\n\n[![NPM latest](https://img.shields.io/npm/v/@cubux/effector-persistent.svg)](https://www.npmjs.com/package/@cubux/effector-persistent)\n\nPersist data in effector store.\n\n```ts\nimport { createStore } from \"effector\";\nimport { withPersistent } from \"@cubux/effector-persistent\";\nimport { createLocalStorageDriver } from \"@cubux/storage-driver\";\n\nconst $accessToken = withPersistent(\n  createStore(\"\"),\n  createLocalStorageDriver(),\n  \"accessToken\"\n);\n```\n\n## Install\n\n```sh\nnpm i @cubux/effector-persistent\n```\n\n## API\n\nSee also [`@cubux/storage-driver`](https://github.com/cubux-net/ts-storage-driver).\nIt supports `localStorage`/`sessionStorage` and `indexedDB`.\n\n### `withPersistent()`\n\nRegister persistent data handling for the given store with the given driver.\nData from `store` will be stored in `driver` with the given `key`. Function\nreturns input `store`, so it can be used inline.\n\nType of `store` can be `Store` only when `wakeUp` options is defined. Otherwise\na `StoreWritable` is needed.\n\n```ts\nfunction withPersistent\u003cKey, Value, Serialized = Value\u003e(\n  store:    Store\u003cValue\u003e\n          | StoreWritable\u003cValue\u003e,\n  driver:   StoreDriverSingle\u003cKey, Serialized\u003e\n          | Promise\u003cStoreDriverSingle\u003cKey, Serialized\u003e\u003e,\n  key:      Key,\n  options?: WithPersistentOptions\u003cValue, Value, Serialized\u003e\n): typeof store\n```\n\nExample:\n\n```ts\nimport { createStore } from \"effector\";\nimport { withPersistent } from \"@cubux/effector-persistent\";\nimport { createLocalStorageDriver } from \"@cubux/storage-driver\";\n\nconst lsDriver = createLocalStorageDriver();\nconst $storeA = withPersistent(createStore(0), lsDriver, \"keyA\");\nconst $storeB = withPersistent(createStore(\"\"), lsDriver, \"keyB\");\n```\n\nIn the example above `$storeA` and `$storeB` will use `localStorage` for\npersistent data with keys `\"persistent:keyA\"` and `\"persistent:keyB\"`\nrespectively.\n\n### `withPersistentMap()`\n\nRegister persistent data handling for the given `ReadonlyMap` store with the\ngiven driver. Data from `store` will be stored in `driver` with corresponding\nkeys from `ReadonlyMap`. Function returns input `store`, so it can be used\ninline.\n\nType of `store` can be `Store` only when `wakeUp` options is defined. Otherwise\na `StoreWritable` is needed.\n\n```ts\nfunction withPersistentMap\u003cKey, Value, Serialized = Value\u003e(\n  store:    Store\u003cReadonlyMap\u003cKey, Value\u003e\u003e\n          | StoreWritable\u003cReadonlyMap\u003cKey, Value\u003e\u003e,\n  driver:   StoreDriver\u003cKey, Serialized\u003e\n          | Promise\u003cStoreDriver\u003cKey, Serialized\u003e\u003e,\n  options?: WithPersistentOptions\u003cReadonlyMap\u003cKey, Value\u003e, Value, Serialized\u003e\n): typeof store\n```\n\nUnder the hood on every `store` change it will detect changes in underlying\n`Map` entries and will send to `driver` only those was changed.\n\n**Notice:** Serialization when used with `options` will be applied to individual\nvalues `Value` rather than to whole `Map\u003cKey, Value\u003e`.\n\nExample:\n\n```ts\nimport { createStore } from \"effector\";\nimport { withPersistentMap } from \"@cubux/effector-persistent\";\nimport { createLocalStorageDriver } from \"@cubux/storage-driver\";\n\nconst $storeMap = withPersistentMap(\n  createStore\u003cReadonlyMap\u003cstring, number\u003e\u003e(new Map()),\n  createLocalStorageDriver()\n);\n```\n\nIn the example above `$storeMap` will use `localStorage` for persistent data\nwith keys starting with `\"persistent:\"`, so every entry from `ReadonlyMap` will\nhave its own row in `localStorage`.\n\n### `interface WithPersistentFlushEvent`\n\nA payload for flush events.\n\n| Property | Type     | Description                       |\n|----------|----------|-----------------------------------|\n| `id`     | `symbol` | Identifier for current flush flow |\n\n### `interface WithPersistentFlushFailEvent`\n\nA payload for flush events.\n\nThis interface extends `WithPersistentFlushEvent` with the following additional\nproperties:\n\n| Property | Type      | Description           |\n|----------|-----------|-----------------------|\n| `error`  | `unknown` | Reason of the failure |\n\n### `interface WithPersistentOptions`\n\nCommon options for persistent storage.\n\n```ts\ninterface WithPersistentOptions\u003c\n  State = any,\n  Value = State,\n  Serialized = Value\n\u003e\n```\n\n| Options          | Type                                                                          | Default     | Description                                                                                                                                                                                      |\n|------------------|-------------------------------------------------------------------------------|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `flushDelay`     | `number`                                                                      | `undefined` | Debounce 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.                |\n| `onFlushStart`   | `EventCallable\u003cWithPersistentFlushEvent\u003e`                                     | `undefined` | An 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.                                              |\n| `onFlushDone`    | `EventCallable\u003cWithPersistentFlushEvent\u003e`                                     | `undefined` | An Event to trigger when flush succeeds. An `id` in payload refers to `id` from appropriate `onFlushStart` payload.                                                                              |\n| `onFlushFail`    | `EventCallable\u003cWithPersistentFlushFailEvent\u003e`                                 | `undefined` | An Event to trigger when flush fails. An `id` in payload refers to `id` from appropriate `onFlushStart` payload.                                                                                 |\n| `onFlushFinally` | `EventCallable\u003cWithPersistentFlushEvent\u003e`                                     | `undefined` | An 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. |\n| `readOnly`       | `EventCallable\u003cboolean\u003e`                                                      | `undefined` | A `filter` Store to disable writes to Driver.                                                                                                                                                    |\n| `wakeUp`         | \u003ccode\u003eStoreWritable\u0026lt;State\u0026gt; \u0026#124; ((state: State) =\u0026gt; void)\u003c/code\u003e    | `undefined` | Alternative target which will receive initial state read from driver on initialization. When `undefined`, the source StoreWritable will be used.                                                 |\n| `onBeforeWakeUp` | `() =\u003e void`                                                                  | `undefined` | A callback to be called before \"wake up\" prodecure.                                                                                                                                              |\n| `onAfterWakeUp`  | `() =\u003e void`                                                                  | `undefined` | A callback to be called after \"wake up\" prodecure.                                                                                                                                               |\n| `serialize`      | \u003ccode\u003e(input: Value) =\u0026gt; Serialized \u0026#124; Promise\u0026lt;Serialized\u0026gt;\u003c/code\u003e | `undefined` | Serialization before writing data to driver.                                                                                                                                                     |\n| `unserialize`    | \u003ccode\u003e(output: Serialized) =\u0026gt; Value \u0026#124; Promise\u0026lt;Value\u0026gt;\u003c/code\u003e     | `undefined` | Unserialization after reading data from driver.                                                                                                                                                  |\n\n## Helper API\n\n### `flushDelayed()`\n\nSetup delayed flushes from `source` unit to `target` unit with whe given debounce\ninterval.\n\nPrefer [`patronum` `debounce()`](https://patronum.effector.dev/methods/debounce/)\ninstead.\n\n```ts\nfunction flushDelayed\u003cT\u003e(options: Options\u003cT\u003e): (() =\u003e void);\n```\n\nIt takes options described below and returns a function to stop watching and\ninterrupt planned flush.\n\n| Options      | Type                                              | Default      | Description                                                               |\n|--------------|---------------------------------------------------|--------------|---------------------------------------------------------------------------|\n| `source`     | \u003ccode\u003eStore\u0026lt;T\u0026gt; \u0026#124; Event\u0026lt;T\u0026gt;\u003c/code\u003e | **Required** | Source unit to watch                                                      |\n| `target`     | `(payload: T) =\u003e void`                            | **Required** | Receiver to flush data to                                                 |\n| `flushDelay` | \u003ccode\u003enumber \u0026#124; Store\u0026lt;number\u0026gt;\u003c/code\u003e    | `1000`       | Debounce timeout to await before flush                                    |\n| `filter`     | \u003ccode\u003eStore\u0026lt;boolean\u0026gt;\u003c/code\u003e                 | `undefined`  | When specified, flushes will work only when this filter `Store` is `true` |\n\nActual flush `target` will be called only after `source` unit will stop\ntriggering for at least duration in `flushDelay`. That is while `source` is\nkeeping triggering continuous within this duration, flush `target` will never\nbe called.\n\nWhen `flushDelay` is `Store\u003cnumber\u003e`, it's value will take effect only on next\n`source` update.\n\nWhen `filter` is used, it will abort current planned flush, when its value\nbecomes `false`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcubux-net%2Feffector-persistent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcubux-net%2Feffector-persistent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcubux-net%2Feffector-persistent/lists"}