{"id":13527319,"url":"https://github.com/elgerlambert/redux-localstorage","last_synced_at":"2026-01-14T17:40:44.861Z","repository":{"id":35091019,"uuid":"39250787","full_name":"elgerlambert/redux-localstorage","owner":"elgerlambert","description":"Store enhancer that syncs (a subset) of your Redux store state to localstorage.","archived":false,"fork":false,"pushed_at":"2022-01-23T11:23:42.000Z","size":72,"stargazers_count":1310,"open_issues_count":35,"forks_count":107,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-11-18T07:02:47.316Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"microsoft/recommenders","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elgerlambert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-17T11:25:14.000Z","updated_at":"2025-10-16T09:36:40.000Z","dependencies_parsed_at":"2022-07-08T13:30:34.346Z","dependency_job_id":null,"html_url":"https://github.com/elgerlambert/redux-localstorage","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/elgerlambert/redux-localstorage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgerlambert%2Fredux-localstorage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgerlambert%2Fredux-localstorage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgerlambert%2Fredux-localstorage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgerlambert%2Fredux-localstorage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elgerlambert","download_url":"https://codeload.github.com/elgerlambert/redux-localstorage/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgerlambert%2Fredux-localstorage/sbom","scorecard":{"id":372417,"data":{"date":"2025-08-11","repo":{"name":"github.com/elgerlambert/redux-localstorage","commit":"53a885366fa2c87807d25a595ad789bd558c5e71"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Code-Review","score":1,"reason":"Found 5/26 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 9 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T13:17:31.150Z","repository_id":35091019,"created_at":"2025-08-18T13:17:31.151Z","updated_at":"2025-08-18T13:17:31.151Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28428911,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T16:38:47.836Z","status":"ssl_error","status_checked_at":"2026-01-14T16:34:59.695Z","response_time":107,"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":[],"created_at":"2024-08-01T06:01:45.693Z","updated_at":"2026-01-14T17:40:44.847Z","avatar_url":"https://github.com/elgerlambert.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Marks","React, Redux"],"sub_categories":["[React - A JavaScript library for building user interfaces](http://facebook.github.io/react)"],"readme":"redux-localstorage\n==================\n\nStore enhancer that syncs (a subset) of your Redux store state to localstorage.\n\n**NOTE:** Be sure to check out the [1.0-breaking-changes](https://github.com/elgerlambert/redux-localstorage/tree/1.0-breaking-changes) branch (available on npm as `redux-localstorage@rc`). It includes support for flexible storage backends, including (but not limited to) `sessionStorage` and react-natives' `AsyncStorage`.\n\n## Installation\n```js\nnpm install --save redux-localstorage\n```\n\n## Usage\n```js\nimport {compose, createStore} from 'redux';\nimport persistState from 'redux-localstorage'\n\nconst enhancer = compose(\n  /* [middlewares] */,\n  persistState(/*paths, config*/),\n)\n\nconst store = createStore(/*reducer, [initialState]*/, enhancer)\n```\n\n### persistState(paths, config)\n#### paths\n```js\ntype paths = Void | String | Array\u003cString\u003e\n```\nIf left `Void`, persistState will sync Redux's complete store state with localStorage. Alternatively you may specify which part(s) of your state should be persisted.\n\n**Note:** Currently no support for nested paths. Only \"top-level\" paths are supported, i.e. state[path]. If your needs are more complex and you require more control over\nwhich parts of your store's state should be persisted you can define your own strategy through [config.slicer](#configslicer)\n\n#### config\n##### config.key\n```js\ntype config.key = String\n```\nThe localStorage key used to store state. The default value is `redux`.\n\n##### config.slicer\n```js\ntype config.slicer = (paths: Any) =\u003e (state: Collection) =\u003e subset: Collection\n```\nConfig.slicer allows you to define your own function which will be used to determine which parts should be synced with localStorage. It should look something like this:\n```js\nfunction myCustomSlicer (paths) {\n  return (state) =\u003e {\n    let subset = {}\n    /*Custom logic goes here*/\n    return subset\n  }\n}\n```\nIt is called with the paths argument supplied to persistState. It should return a function that will be called with the store's state, which should return a subset that matches the original shape/structure of the store - it's this subset that'll be persisted.\n\nIf, for example, you want to dynamically persist parts of your store state based on a user's preference, defining your own `slicer` allows you to do that. Simply add something along the following lines to your customSlicer function:\n\n```js\npaths.forEach((path) =\u003e {\n  if (state[path].persistToLocalStorage)\n    subset[path] = state[path]\n}\n```\n\n## Immutable Data\nIf you're using immutable collections or some other custom collection, redux-localstorage exposes a number of functions that can be overridden by providing the following config options. These allow you to specify your own transformations based on your needs. If you're using ordinary javascript Objects, Arrays or primitives, you shouldn't have to concern yourself with these options.\n\n##### config.serialize\n```js\ntype config.serialize = (subset: Collection) =\u003e serializedData: String\n```\nThe default serialization strategy is JSON.stringify. Specifying a serialize function as part of your config will override this.\nThis function receives a single argument (the subset of your store's state about to be persisted) and should return a serialized (i.e. stringified) representation thereof. \n\n##### config.deserialize\n```js\ntype config.deserialize = (serializedData: String) =\u003e subset: Collection\n```\nThe default deserialization strategy is JSON.parse. Specifying a deserialize function as part of your config will override this.\nThis function receives a single argument (a serialized representation of your persisted state) and should return the data in a format that's expected by your application.\n\n##### config.merge\n```js\ntype config.merge = (initialState: Collection, persistedState: Collection) =\u003e finalInitialState: Collection\n```\nDuring initialization any persisted state is merged with the initialState passed in as an argument to `createStore`.\nThe default strategy `extends` the initialState with the persistedState. Override this function if that doesn't work for you. **Note:** this is only required if you want to merge values within an immutable collection. If your values are immutable, but the object that holds them is not, the default strategy should work just fine.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felgerlambert%2Fredux-localstorage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felgerlambert%2Fredux-localstorage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felgerlambert%2Fredux-localstorage/lists"}