{"id":19195281,"url":"https://github.com/fixate/xstream-store","last_synced_at":"2025-06-26T00:04:13.186Z","repository":{"id":57402319,"uuid":"135120427","full_name":"fixate/xstream-store","owner":"fixate","description":"A redux-like store module for xstream","archived":false,"fork":false,"pushed_at":"2018-08-17T13:50:27.000Z","size":164,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-26T00:03:38.858Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/fixate.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":"2018-05-28T06:44:56.000Z","updated_at":"2021-08-14T03:31:13.000Z","dependencies_parsed_at":"2022-09-17T06:51:09.429Z","dependency_job_id":null,"html_url":"https://github.com/fixate/xstream-store","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/fixate/xstream-store","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fixate%2Fxstream-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fixate%2Fxstream-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fixate%2Fxstream-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fixate%2Fxstream-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fixate","download_url":"https://codeload.github.com/fixate/xstream-store/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fixate%2Fxstream-store/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261973725,"owners_count":23238586,"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":[],"created_at":"2024-11-09T12:09:30.241Z","updated_at":"2025-06-26T00:04:13.113Z","avatar_url":"https://github.com/fixate.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xstream-store\n\n[![Build Status](https://travis-ci.org/fixate/xstream-store.svg?branch=master)](https://travis-ci.org/fixate/xstream-store)\n[![npm version](https://badge.fury.io/js/xstream-store.svg)](https://badge.fury.io/js/xstream-store)\n[![codecov](https://codecov.io/gh/fixate/xstream-store/branch/master/graph/badge.svg)](https://codecov.io/gh/fixate/xstream-store)\n\n\nA redux-like store module for xstream inspired by redux.\n\nTake the pain out of handling side-effects with the power of observables. Eliminate\nthe need for use of middleware such as `redux-thunk`, and side-effect handlers such\nas `redux-saga`.\n\n## Install\n\n```\n$ npm i xstream-store xstream\n```\n\n## Example\n\nView the source in `examples/`:\n\n```bash\n$ node examples/counter\n```\n\n## Usage\n\n```javascript\n// my-streamed-counter.js\n\nconst ADD_TYPE = 'add';\nconst addActionCreator = value =\u003e ({\n  type: ADD_TYPE,\n  value,\n});\n\nconst RESET_TYPE = 'reset';\nconst resetAction = {\n  type: RESET_TYPE,\n};\n\nconst initialState = {value: 0};\n\nconst counter$Creator = select =\u003e\n  // our counter stream that only receives `counter` state\n  xs\n    .merge(\n      select(ADD_TYPE).map(action =\u003e state =\u003e ({\n        ...state,\n        value: state.value + action.value,\n      })),\n      select(RESET).map(_ =\u003e _ =\u003e initialState)\n    )\n    // provide initialState in a callback\n    .startWith(() =\u003e initialState);\n\nconst counterEffectsCreator = (select, dispatch) =\u003e {\n  // a stream of all actions\n  const action$ = select();\n  // a stream of add actions\n  const addAction$ = select(ADD_TYPE);\n  // a stream of reset actions\n  const reset$ = select(RESET_TYPE);\n\n  action$.addListener({\n    next(action) {\n      console.log('I log on every action', action);\n    }\n  })\n\n  add$.addListener({\n    next(action) {\n      console.log('I log every add action', action);\n\n      // dispatch a reset when our counter's value is greater than 3\n      if (action.value \u003e 3) {\n        dispatch(resetAction);\n      }\n    }\n  })\n\n  reset$.addListener({\n    next() {\n      console.log('Counter reset!');\n    }\n  })\n};\n\nexport {\n  addAction,\n  counter$Creator,\n  counterEffectsCreator,\n}\n```\n\n```javascript\n// store.js\nimport createStore from 'xstream-store';\nimport {\n  addActionCreator,\n  counterEffectsCreator,\n  counterStreamCreators\n} from './my-streamed-counter'\n\nconst add1Action = addActionCreator(1);\n\nconst streamCreatorMap = {\n  counter: counterStreamCreator,\n}\n\nconst effectCreators = [\n  counterEffectsCreator,\n  // fooEffectsCreator\n];\n\nconst store = createStore(streamCreatorMap, effectCreators);\n\n// subscribe to your state stream\nstore.state$.addListener({\n  next(state) { console.log(`entire state: ${state}`) },\n});\n\nconst counterState = store.state$\n                      .map(({counter}) =\u003e counter)\n                      .addListener({\n                        next(counterState) {\n                          console.log(`counter state: ${state}`)\n                        }\n                      });\n\n// dispatch actions\nstore.dispatch(add1Action);\n// entire state: {counter: { value: 1 }}\n// counter state: { value: 1 }\n\nstore.dispatch(add1Action);\n// entire state: {counter: { value: 2 }}\n// counter state: { value: 2 }\n```\n\n### `createStore`\n\n`xstream-store` exports a single function, `createStore`. `createStore` returns an object containing the initial state of the store, a stream of the current state, and a dispatch function for updating values in the store\n\n```javascript\nconst streamCreatorMap = {\n  counter: myCounterStreamCeator\n};\n\nconst effectCreators = [\n  myCounterEffectCreator\n];\n\nconst {dispatch, state$, initialState} = createStore(streamCreatorMap, effectCreators);\n```\n\n| Parameter        | Type                              | Required | Description                                                                                                                                                                                                                                    |\n|------------------|-----------------------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| streamCreatorMap | obj: {   [name]: streamCreator, } | true     | An object mapping each streamCreator to a key on the store                                                                                                                                                                                     |\n| effectCreators   | [effectCreator]                   | false    | An array of effect creators. `xstream-store` will map over each effect creator, passing in a `select` function for filtering actions within the effect creator, and a `dispatch` action for dispatching actions from within the effect creator |\n\n#### `state$`\n\nThe state stream returned by `createStore`. Create subscribers to `state$` to respond to changes to state:\n\n```javascript\nstate$.map(({counter}) =\u003e counter)\n      .subscribe({\n        next(counter) {\n          // do something with latest counter value\n        }\n      });\n```\n\n#### `dispatch`\n\nDispatch actions to update the state of your store:\n\n```javascript\nconst incrementAction = {type: 'increment'}\nconst addActionCreator = n =\u003e ({\n  type: 'add',\n  value: n,\n});\n\n// increment counter value\ndispatch(incrementAction);\n\n// add 5 to counter value\ndispatch(addActionCreator(5))\n```\n\n#### `initialState`\n\nThe initial state of the entire store, as defined by the initial state of each stream creator.\n\n### Actions\n\n### Stream Creator\n\n#### `select`\n\n### Effects Creator\n\n#### `select`\n\n#### `dispatch`\n\n###\n\n## Related Libraries\n\n- [xstream-store-resource](https://github.com/fixate/xstream-store-resource) - easily generate streams for asynchronous requests\n- [react-xstream-store](https://github.com/fixate/react-xstream-store) - connect React components to an xstream store\n\n## Todo\n\n- [ ] add usage\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffixate%2Fxstream-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffixate%2Fxstream-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffixate%2Fxstream-store/lists"}