{"id":19189656,"url":"https://github.com/ovrmrw/reactive-store","last_synced_at":"2025-04-15T01:37:14.470Z","repository":{"id":57317177,"uuid":"79190376","full_name":"ovrmrw/reactive-store","owner":"ovrmrw","description":"Most Simple Reactive Store using RxJS by @ovrmrw","archived":false,"fork":false,"pushed_at":"2017-04-08T04:18:38.000Z","size":99,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-04T09:43:08.396Z","etag":null,"topics":["angular","angular2","react","rxjs","typescript"],"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/ovrmrw.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2017-01-17T05:03:35.000Z","updated_at":"2018-07-13T18:08:25.000Z","dependencies_parsed_at":"2022-08-25T20:40:41.648Z","dependency_job_id":null,"html_url":"https://github.com/ovrmrw/reactive-store","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovrmrw%2Freactive-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovrmrw%2Freactive-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovrmrw%2Freactive-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ovrmrw%2Freactive-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ovrmrw","download_url":"https://codeload.github.com/ovrmrw/reactive-store/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248990379,"owners_count":21194747,"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","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":["angular","angular2","react","rxjs","typescript"],"created_at":"2024-11-09T11:30:40.682Z","updated_at":"2025-04-15T01:37:14.454Z","avatar_url":"https://github.com/ovrmrw.png","language":"TypeScript","readme":"# ovrmrw-reactive-store\nMost Simple Reactive Store using RxJS\n\n---\n\n**(!) TypeScript 2.1 or later is needed.**\n\nSimple key-value store like Flux concept for frond-end apps.\n\nFlux and Redux are of course good ideas.\n\nBut writing Actions, ActionCreators and Reducers for small apps is exaggerated and painful.\n\nThat is why that I wrote a Simple Store.\n\nIn web apps world, we have to consider all events as async, so Reactive Concept is best match to that.\n\nThis store is a key-value reactive store based on RxJS, and **Redux is used for storing states** in the Observable world.\nSo you can use any Redux Middleware as you like, for example `redux-logger` and so on.\n\nTo handle **states, time flow and events** easily, Simple Reactive Store (using RxJS) was born.\n\n---\n\n## Install from npm\n```\n$ npm install --save ovrmrw-reactive-store\nor\n$ yarn add ovrmrw-reactive-store\n```\n\n---\n\nUsage: [\\_\\_test\\_\\_/index.ts](https://github.com/ovrmrw/reactive-store/blob/master/__test__/index.ts)\n\nExample React app: [ovrmrw/my-first-react-typescript](https://github.com/ovrmrw/my-first-react-typescript)\n\nExample Angular app: [ovrmrw/angular-simple-redux-starter](https://github.com/ovrmrw/angular-simple-redux-starter)\n\n---\n\n## Usage detail\n\nDeclare `interface` for the States.\n\n```\ninterface AppState {\n  increment: IncrementState,\n  timestamp: number,\n}\n\ninterface IncrementState {\n  counter: number,\n}\n```\n\nCreate `initialState` using interfaces above.\n\n```\nconst initialState: AppState = {\n  increment: {\n    counter: 0,\n  },\n  timestamp: 0,\n}\n```\n\nGenerate an object for ObjectKeys by `getObjectKeys` method. The first layer keys of `initialState` will be string literals of `KEY`.\n\n```\nconst KEY = getObjectKeys(initialState)\n```\n\nAbove code is equivalent to\n\n```\nconst KEY = {\n  increment: 'increment',\n  timestamp: 'timestamp'\n}\n```\n\nGenerate a store instance by `getReactiveStoreAsSingleton` method with `initialState` and some options.\n\n```\nimport * as logger from 'redux-logger'\n\nconst store = getReactiveStoreAsSingleton(initialState, {\n  useFreeze: true, // DEFAULT: false ... whether to freeze State object before be sent to getter function.\n  reduxMiddlewares: [logger()], // In this case, Store uses a Redux Middleware for logger.\n  useReduxDevToolsExtension: true, // DEFAULT: false ... whether to enable Redux DevTools Extension.\n})\n```\n\nDue to the `reduxMiddlewares` option, you can use any Redux Middleware.\n\nNext, set a value to the states.\n\n```\nstore.setter(KEY.increment, (p) =\u003e ({counter: p.counter + 1}))\n\n/* The variable \"p\" is a part of the state of AppState that indicates IncrementState under the \"increment\" key. */\n```\n\n`setter` is **chainable**.\n\n```\nstore.setter(KEY.increment, (p) =\u003e ({counter: p.counter + 1}))\n  .then(() =\u003e store.setter(KEY.timestamp, new Date().getTime()))\n\n/* The second setter is invoked after the first setter resolved. */\n```\n\n**Async function** is acceptable.\n\n```\nstore.setter(KEY.increment, (p) =\u003e Promise.resolved(({counter: p.counter + 1})))\n\nstore.setter(KEY.increment, (p) =\u003e Promise.resolved((q) =\u003e ({counter: q.counter + 1})))\n\nstore.setter(KEY.increment, Promise.resolved(({counter: 1})))\n\nstore.setter(KEY.increment, Promise.resolved((p) =\u003e ({counter: p.counter + 1})))\n```\n\nYou can also get **all of the state** instead of a part of the state.\n\n```\nstore.setter(KEY.increment, (_, a) =\u003e ({counter: a.increment.counter + 1})))\n\n/* The variable \"a\" is all of the state. */\n```\n\nGet your states. The type of `getter()` is `Observable\u003cAppState\u003e`.\n\n```\nstore.getter()\n  .subscribe(state =\u003e {\n    value = state.increment.counter\n  })\n```\n\nTo get more controll, filter the streams by `filterByUpdatedKey` operator.\n\n```\nstore.getter()\n  .filterByUpdatedKey(KEY.timestamp) // pass when \"timestamp\" key is updated.\n  .subscribe(state =\u003e {\n    value = state.timestamp\n  })\n```\n\n---\n\n## Setup\n```\n$ yarn install\nor\n$ npm install\n```\n\n## Test\n```\n$ npm test\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fovrmrw%2Freactive-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fovrmrw%2Freactive-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fovrmrw%2Freactive-store/lists"}