{"id":20129378,"url":"https://github.com/ryanmorr/define-store","last_synced_at":"2026-02-19T13:02:31.019Z","repository":{"id":43954808,"uuid":"256802461","full_name":"ryanmorr/define-store","owner":"ryanmorr","description":"Define custom stores for reactive programming","archived":false,"fork":false,"pushed_at":"2025-02-20T01:22:38.000Z","size":117,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-12T02:06:57.570Z","etag":null,"topics":["javascript","observable","reactive","store"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryanmorr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-18T16:37:08.000Z","updated_at":"2024-10-22T16:33:33.000Z","dependencies_parsed_at":"2025-01-13T08:40:51.047Z","dependency_job_id":null,"html_url":"https://github.com/ryanmorr/define-store","commit_stats":{"total_commits":19,"total_committers":1,"mean_commits":19.0,"dds":0.0,"last_synced_commit":"0cf168610b56e4522df11cffb2d8896d9593572e"},"previous_names":["ryanmorr/create-store"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ryanmorr/define-store","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fdefine-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fdefine-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fdefine-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fdefine-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryanmorr","download_url":"https://codeload.github.com/ryanmorr/define-store/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fdefine-store/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29614591,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T10:52:55.328Z","status":"ssl_error","status_checked_at":"2026-02-19T10:52:26.323Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6: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":["javascript","observable","reactive","store"],"created_at":"2024-11-13T20:34:00.847Z","updated_at":"2026-02-19T13:02:31.001Z","avatar_url":"https://github.com/ryanmorr.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# define-store\n\n[![Version Badge][version-image]][project-url]\n[![License][license-image]][license-url]\n[![Build Status][build-image]][build-url]\n\n\u003e Define custom stores for reactive programming\n\n## Install\n\nDownload the [CJS](https://github.com/ryanmorr/define-store/raw/master/dist/cjs/define-store.js), [ESM](https://github.com/ryanmorr/define-store/raw/master/dist/esm/define-store.js), [UMD](https://github.com/ryanmorr/define-store/raw/master/dist/umd/define-store.js) versions or install via NPM:\n\n```sh\nnpm install @ryanmorr/define-store\n```\n\n## Usage\n\nEasily create customizable observable stores that allow you control every aspect of it's behavior and API, including how it's created, how and when it's internal value is read and written, and how subscribers are handled. This allows you to create stores with specific functionality and still maintain interoperability with different reactive libraries.\n\n```javascript\nimport defineStore from '@ryanmorr/define-store';\n\n// Define a store with a callback function that is provided a function to get the\n// internal value, a function to set the internal value, a function to add\n// subscribers, and the subscribers array as the 4 parameters\nconst store = defineStore((get, set, subscribe, subscribers) =\u003e {\n\n    // Return a function for creating store instances with custom arguments\n    return (initialValue) =\u003e {\n\n        // Set the initial value upon creation\n        set(initialValue);\n\n        // This return object exposes the external API for interacting\n        // with a store instance\n        return {\n\n            // Add `get` method\n            get,\n\n            // Add `set` method\n            set(...args) {\n\n                // The `set` function supports multiple arguments that will all be\n                // passed to the subscribers when called, only the first argument\n                // will be set to the new internal value\n                set(...args);\n            },\n\n            // By default, the `subscribe` function is automatically added to the\n            // return object unless it is explicitly overridden\n            subscribe(callback) {\n\n                // The `subscribe` function returns an `unsubscribe` function for the\n                // subscriber when called\n                const unsubscribe = subscribe(callback);\n\n                // Override `unsubscribe` and return it as a method of an object instead\n                // of a function\n                return {\n                    unsubscribe() {\n                        unsubscribe();\n\n                        // The `subscribers` array is live, it's useful for executing\n                        // code when the first subscriber is added or the last is removed\n                        if (subscribers.length === 0) {\n                            \n                        }\n                    }\n                };\n            }\n        };\n    };\n});\n\n// Create an instance of the store with an initial value\nconst value = store(100);\n\n// Add a subscriber\nconst subscriber = value.subscribe((newValue) =\u003e console.log(newValue));\n\n// Get the stored value\nvalue.get(); //=\u003e 100\n// Set the stored value\nvalue.set(200);\n// Get the new stored value\nvalue.get(); //=\u003e 200\n\n// Remove subscriber\nsubscriber.unsubscribe();\n\n// Supports implicit type conversions\nvalue.toString(); //=\u003e \"200\"\nvalue.valueOf(); //=\u003e 200\nvalue.toJSON(); //=\u003e 200\nawait value; //=\u003e 200\n```\n\n## Examples\n\nYou can make all kinds of different observable stores, for example, here's a basic function-based store:\n\n```javascript\nconst store = defineStore((get, set) =\u003e (value) =\u003e {\n    set(value);\n    return (...args) =\u003e {\n        if (args.length === 1) {\n            set(args[0]);\n        }\n        return get();\n    };\n});\n\nconst value = store('foo');\n\nconst subscribe = value.subscribe((val) =\u003e console.log(val));\n\nvalue(); //=\u003e \"foo\"\nvalue('bar');\nvalue(); //=\u003e \"bar\"\n```\n\nAnd how about a computed store to go with it:\n\n```javascript\nconst computed = defineStore((get, set) =\u003e (deps, callback) =\u003e {\n    const setValue = () =\u003e set(callback(deps.map((dep) =\u003e dep())));\n    deps.forEach((dep) =\u003e dep.subscribe(setValue));\n    setValue();\n    return get;\n});\n\nconst firstName = store('John');\nconst lastName = store('Doe');\nconst fullName = computed([firstName, lastName], ([first, last]) =\u003e `${first} ${last}`);\n\nconst subscribe = fullName.subscribe((name) =\u003e console.log(name));\n\nfullName(); //=\u003e \"John Doe\"\nfirstName('Jane');\nfullName(); //=\u003e \"Jane Doe\"\nlastName('Smith');\nfullName(); //=\u003e \"Jane Smith\"\n```\n\nOr maybe a simple toggle store:\n\n```javascript\nconst toggle = defineStore((get, set) =\u003e (on = false) =\u003e {\n    set(on);\n    return {\n        isOn: get,\n        on: () =\u003e set(true),\n        off: () =\u003e set(false),\n        toggle: () =\u003e set(!get())\n    };\n});\n\nconst toggler = toggle();\n\nconst subscribe = toggler.subscribe((on) =\u003e console.log(on));\n\ntoggler.on();\ntoggler.isOn(); //=\u003e true\ntoggler.off();\ntoggler.isOn(); //=\u003e false\ntoggler.toggle();\ntoggler.isOn(); //=\u003e true\n```\n\nDon't forget your Redux-style reducer store:\n\n```javascript\nconst reduce = defineStore((get, set) =\u003e (reducer, initialState) =\u003e {\n    set(initialState);\n    return {\n        getState: get,\n        dispatch: (action) =\u003e set(reducer(get(), action))\n    };\n});\n\nfunction reducer(state, action) {\n    switch (action.type) {\n        case 'increment':\n            return {count: state.count + 1};\n        case 'decrement':\n            return {count: state.count - 1};\n        default:\n            return state;\n    }\n}\n\nconst state =  {count: 0};\nconst counter = reduce(reducer, state);\n\nconst subscribe = counter.subscribe((state) =\u003e console.log(state));\n\ncounter.dispatch({type: 'increment'});\ncounter.getState(); //=\u003e {count: 1}\ncounter.dispatch({type: 'decrement'});\ncounter.getState(); //=\u003e {count: 0}\n```\n\n## License\n\nThis project is dedicated to the public domain as described by the [Unlicense](http://unlicense.org/).\n\n[project-url]: https://github.com/ryanmorr/define-store\n[version-image]: https://img.shields.io/github/package-json/v/ryanmorr/define-store?color=blue\u0026style=flat-square\n[build-url]: https://github.com/ryanmorr/define-store/actions\n[build-image]: https://img.shields.io/github/actions/workflow/status/ryanmorr/define-store/node.js.yml?style=flat-square\n[license-image]: https://img.shields.io/github/license/ryanmorr/define-store?color=blue\u0026style=flat-square\n[license-url]: UNLICENSE","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanmorr%2Fdefine-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryanmorr%2Fdefine-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanmorr%2Fdefine-store/lists"}