{"id":16229542,"url":"https://github.com/matssom/storable-state","last_synced_at":"2025-07-23T01:32:47.840Z","repository":{"id":56023058,"uuid":"315787500","full_name":"matssom/storable-state","owner":"matssom","description":":package: Simple state management library with local storage integration","archived":false,"fork":false,"pushed_at":"2020-11-30T17:23:44.000Z","size":226,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-08T05:42:12.485Z","etag":null,"topics":["derived","localstorage","readable","state","state-management","storable","storage","store","writable"],"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/matssom.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}},"created_at":"2020-11-25T00:35:19.000Z","updated_at":"2023-07-28T02:06:30.000Z","dependencies_parsed_at":"2022-08-15T11:40:19.088Z","dependency_job_id":null,"html_url":"https://github.com/matssom/storable-state","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/matssom/storable-state","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matssom%2Fstorable-state","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matssom%2Fstorable-state/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matssom%2Fstorable-state/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matssom%2Fstorable-state/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matssom","download_url":"https://codeload.github.com/matssom/storable-state/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matssom%2Fstorable-state/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266602790,"owners_count":23954694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"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":["derived","localstorage","readable","state","state-management","storable","storage","store","writable"],"created_at":"2024-10-10T12:58:32.930Z","updated_at":"2025-07-23T01:32:47.801Z","avatar_url":"https://github.com/matssom.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Storable State\n\nThere are lot's of state management libraries. This one takes inspiration from the state management system that comes with svelte. It is simple, intuitive and powerful at the same time.\n\n## Stores\n\nThe library is comprised of 4 store types. These 4 types are `writable`, `readable`, `storable` and `derived`. Writable can be written to, readable can be read only, storable uses the localStorage api to preserve data between site refresh and derived depends on one or more stores to calculate it's value. All stores can be subscribed to.\n\n## Documentation\n\n### Writable\n\nA writable store can be created with an initial value and optionally passed a callback function that will be invoked when the first subscriber for that store is register. The return value is another function that will be invoked when the last subscriber is lost.\n\n```js\nimport { writable } from 'storable-state';\n\nconst store = writable(0, () =\u003e {\n\n    console.log(\"Got my first subscriber\");\n\n    return () =\u003e console.log(\"Lost my last subscriber\");\n});\n```\n\n\u003cbr\u003e\n\n`set` is a method that will update the store with a new value.\n\n```js\nstore.set(10);\n```\n\n\u003cbr\u003e\n\n`update` is a method that takes a callback function. It passes the current value to the callback. The return value of the callback is the new store value.\n\n```js\nstore.update(value =\u003e value +1);\n```\n\n\u003cbr\u003e\n\n`subscribe` is a method that accepts a callback that will be called with the new value every time the store value changes. The return of this method is a function you can invoke to unsubscribe.\n\n```js\nconst unsubscribe = store.subscribe(value =\u003e console.log(value));\n\nunsubscribe(); // \u003c-- Call to unsubscribe\n```\n\n\u003cbr\u003e\n\n### Readable\n\nA readable store does the exact same as a writable store, exept that you cannot use the `set` or `update` method. The parameter for the readable store are exactly the same as writable, except that the second parameter is now required. This is the only way to update the store value.\n\nTo update the store value you can use the `set` method provided to the callback. An async method works great here.\n\n```js\nimport { readable } from 'storable-state';\n\nconst store = readable(0, async (set) =\u003e {\n    const count = await fetch('https://api.somewhere.com/count');\n\n    set(count);\n\n    return () =\u003e cleanup();\n});\n```\n\n**NB:** the `set` method is also passed to the writable store if you want to use async there as well.\n\n\u003cbr\u003e\n\n## Storable\n\nThe storable store is essentially the writable store with and extra 2 methods and integration with the localStorage api to preserve state between page refershes. To get this to work you need to provide a key to the storable store. This key will be used to save and retrieve the stored state from localStorage. Storable only supports values that can be parsed with `JSON.stringify()` and `JSON.parse()`. If you are looking to serialize other javascript apis, you can use the serializable store.\n\n```js\nimport { storable } from 'storable-state';\n\n                         ||\n                         \\/\nconst store = storable('count', 0);\n```\n\n**NB:** Also here you can add the setup/teardown callback as the third parameter.\n\n\u003cbr\u003e\n\n`detach` is a method that takes no arguments. It's purpose is to remove the value from local storage so that it won't be preserved on refres. When detach is invoked, the store essentially behaves like a writable store.\n\n```js\nstore.detach();\n```\n\n\u003cbr\u003e\n\n`attach` is a method that does the opposite of detach. It saves the store value back to local storage.\n\n```js\nstore.attach();\n```\n\n\u003cbr\u003e\n\n## Serializable\n\nThe serializable store does the exact same thing as the storable store, except that it also serializes more complex javascript apis like `Map` or `Function`. It uses yahoo's [serialize-javascript](https://github.com/yahoo/serialize-javascript). Check out their repo to see a full list of supported apis.\n\n```js\nimport { serializable } from 'storable-state';\n\nconst personRegister = new Map();\nperson.set(1, 'John Doe');\nperson.set(2, 'Jane Doe');\n\nconst store = serializable('personRegister', personRegister);\n```\n\n\u003cbr\u003e\n\n## Derived\n\nThe derived store takes one store OR an array of stores as first parameter and a callback that will be called with all the respective store values every time one of them changes. The return of this callback will be the new state of the store.\n\n```js\nimport { derived, writable } from 'storable-state';\n\nconst dividend = writable(10);\nconst divisor = writable(2);\n\nconst store = derived(\n    [dividend, divisor],\n    (dividend, divisor) =\u003e {\n        return dividend / divisor;\n    }\n)\n```\n\n\u003cbr\u003e\n\n## Custom Stores\n\nYou can extend the stores with your own buildt in methods if you would like. The basic idea is to destructure any of the stores into their methods and use them in other configurations. Here is an example of how you could achieve this:\n\n```js\nimport { storable } from 'storable';\n\nconst createCountStore = (key = 'count') =\u003e {\n    const { subscribe, set, update, detach, attach } = storable(key, 0);\n\n    return {\n        increase:   () =\u003e update((value) =\u003e value + 1),\n        decrease:   () =\u003e update((value) =\u003e value - 1),\n        reset:      () =\u003e set(0),\n        subscribe,\n        detach,\n        attach\n    }\n}\n\nexport const store = createCountStore('count');\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatssom%2Fstorable-state","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatssom%2Fstorable-state","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatssom%2Fstorable-state/lists"}